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_elapsed_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 void trigger_stop_notifies(DS8Buffer
*buf
)
106 for(i
= 0; i
< buf
->nnotify
; ++i
)
108 DSBPOSITIONNOTIFY
*not = &buf
->notify
[i
];
109 if(not->dwOffset
== (DWORD
)DSBPN_OFFSETSTOP
)
110 SetEvent(not->hEventNotify
);
114 static DWORD CALLBACK
ThreadProc(void *dwUser
)
116 DS8Primary
*prim
= (DS8Primary
*)dwUser
;
120 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
);
122 while(GetMessageA(&msg
, NULL
, 0, 0))
124 if(msg
.message
!= WM_USER
)
127 EnterCriticalSection(prim
->crst
);
128 setALContext(prim
->ctx
);
130 /* OpenAL doesn't support our lovely buffer extensions
131 * so just make sure enough buffers are queued
133 if(!prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
] &&
134 !prim
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] &&
135 !prim
->SupportedExt
[EXT_STATIC_BUFFER
])
137 for(i
= 0;i
< prim
->nbuffers
;++i
)
139 DS8Buffer
*buf
= prim
->buffers
[i
];
140 ALint done
= 0, queued
= QBUFFERS
, state
= AL_PLAYING
;
143 if(buf
->buffer
->numsegs
== 1 || !buf
->isplaying
)
146 alGetSourcei(buf
->source
, AL_SOURCE_STATE
, &state
);
147 alGetSourcei(buf
->source
, AL_BUFFERS_QUEUED
, &queued
);
148 alGetSourcei(buf
->source
, AL_BUFFERS_PROCESSED
, &done
);
152 alSourceUnqueueBuffers(buf
->source
, 1, &which
);
153 while(queued
< QBUFFERS
)
155 which
= buf
->buffer
->buffers
[buf
->curidx
];
156 ofs
= buf
->curidx
*buf
->buffer
->segsize
;
157 if(buf
->curidx
< buf
->buffer
->numsegs
-1)
158 alBufferData(which
, buf
->buffer
->buf_format
,
159 buf
->buffer
->data
+ ofs
, buf
->buffer
->segsize
,
160 buf
->buffer
->format
.Format
.nSamplesPerSec
);
162 alBufferData(which
, buf
->buffer
->buf_format
,
163 buf
->buffer
->data
+ ofs
, buf
->buffer
->lastsegsize
,
164 buf
->buffer
->format
.Format
.nSamplesPerSec
);
166 alSourceQueueBuffers(buf
->source
, 1, &which
);
167 buf
->curidx
= (buf
->curidx
+1)%buf
->buffer
->numsegs
;
170 if(!buf
->curidx
&& !buf
->islooping
)
172 buf
->isplaying
= FALSE
;
176 if(state
!= AL_PLAYING
)
180 IDirectSoundBuffer8_Stop(&buf
->IDirectSoundBuffer8_iface
);
183 alSourcePlay(buf
->source
);
189 for(i
= 0;i
< prim
->nnotifies
;)
191 DS8Buffer
*buf
= prim
->notifies
[i
];
192 IDirectSoundBuffer8
*dsb
= &buf
->IDirectSoundBuffer8_iface
;
193 DWORD status
=0, curpos
=buf
->lastpos
;
195 IDirectSoundBuffer8_GetStatus(dsb
, &status
);
196 IDirectSoundBuffer8_GetCurrentPosition(dsb
, &curpos
, NULL
);
197 if(buf
->lastpos
!= curpos
)
199 trigger_elapsed_notifies(buf
, buf
->lastpos
, curpos
);
200 buf
->lastpos
= curpos
;
202 if(!(status
&DSBSTATUS_PLAYING
))
204 /* Remove this buffer from list and put another at the
205 * current position; don't increment i
207 trigger_stop_notifies(buf
);
208 prim
->notifies
[i
] = prim
->notifies
[--prim
->nnotifies
];
214 LeaveCriticalSection(prim
->crst
);
220 HRESULT
DS8Primary_Create(DS8Primary
*This
, DS8Impl
*parent
)
222 DS3DLISTENER
*listener
;
226 This
->IDirectSoundBuffer_iface
.lpVtbl
= (IDirectSoundBufferVtbl
*)&DS8Primary_Vtbl
;
227 This
->IDirectSound3DListener_iface
.lpVtbl
= (IDirectSound3DListenerVtbl
*)&DS8Primary3D_Vtbl
;
228 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8PrimaryProp_Vtbl
;
230 This
->parent
= parent
;
231 This
->crst
= &parent
->share
->crst
;
232 This
->ctx
= parent
->share
->ctx
;
233 This
->SupportedExt
= parent
->share
->SupportedExt
;
234 This
->ExtAL
= &parent
->share
->ExtAL
;
235 This
->sources
= parent
->share
->sources
;
236 This
->effect
= parent
->share
->effect
;
237 This
->auxslot
= parent
->share
->auxslot
;
239 /* Allocate enough for a WAVEFORMATEXTENSIBLE */
240 wfx
= &This
->format
.Format
;
242 This
->eax_prop
= EnvironmentDefaults
[EAX_ENVIRONMENT_GENERIC
];
244 wfx
->wFormatTag
= WAVE_FORMAT_PCM
;
246 wfx
->wBitsPerSample
= 8;
247 wfx
->nSamplesPerSec
= 22050;
248 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
249 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
252 This
->stopped
= TRUE
;
254 /* Apparently primary buffer size is always 32k,
255 * tested on windows with 192k 24 bits sound @ 6 channels
256 * where it will run out in 60 ms and it isn't pointer aligned
258 This
->buf_size
= 32768;
260 if(This
->SupportedExt
[SOFT_DEFERRED_UPDATES
])
262 This
->DeferUpdates
= This
->ExtAL
->DeferUpdatesSOFT
;
263 This
->ProcessUpdates
= This
->ExtAL
->ProcessUpdatesSOFT
;
267 This
->DeferUpdates
= wrap_DeferUpdates
;
268 This
->ProcessUpdates
= wrap_ProcessUpdates
;
271 /* Make sure DS3DListener defaults are applied to OpenAL */
272 listener
= &This
->listen
;
273 listener
->dwSize
= sizeof(*listener
);
274 listener
->vPosition
.x
= 0.0;
275 listener
->vPosition
.y
= 0.0;
276 listener
->vPosition
.z
= 0.0;
277 listener
->vVelocity
.x
= 0.0;
278 listener
->vVelocity
.y
= 0.0;
279 listener
->vVelocity
.z
= 0.0;
280 listener
->vOrientFront
.x
= 0.0;
281 listener
->vOrientFront
.y
= 0.0;
282 listener
->vOrientFront
.z
= 1.0;
283 listener
->vOrientTop
.x
= 0.0;
284 listener
->vOrientTop
.y
= 1.0;
285 listener
->vOrientTop
.z
= 0.0;
286 listener
->flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
287 listener
->flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
288 listener
->flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
289 hr
= IDirectSound3DListener_SetAllParameters(&This
->IDirectSound3DListener_iface
, listener
, DS3D_IMMEDIATE
);
291 ERR("Could not set 3d parameters: %08"LONGFMT
"x\n", hr
);
293 This
->sizenotifies
= This
->sizebuffers
= parent
->share
->max_sources
;
295 hr
= DSERR_OUTOFMEMORY
;
296 This
->buffers
= HeapAlloc(GetProcessHeap(), 0, This
->sizebuffers
*sizeof(*This
->buffers
));
297 This
->notifies
= HeapAlloc(GetProcessHeap(), 0, This
->sizenotifies
*sizeof(*This
->notifies
));
298 if(!This
->buffers
|| !This
->notifies
)
301 This
->thread_hdl
= CreateThread(NULL
, 0, ThreadProc
, This
, 0, &This
->thread_id
);
302 if(This
->thread_hdl
== NULL
)
308 DS8Primary_Destroy(This
);
312 void DS8Primary_Destroy(DS8Primary
*This
)
314 TRACE("Destroying primary %p\n", This
);
321 timeKillEvent(This
->timer_id
);
322 timeEndPeriod(This
->timer_res
);
323 TRACE("Killed timer\n");
327 PostThreadMessageA(This
->thread_id
, WM_QUIT
, 0, 0);
328 if(WaitForSingleObject(This
->thread_hdl
, 1000) != WAIT_OBJECT_0
)
329 ERR("Thread wait timed out");
330 CloseHandle(This
->thread_hdl
);
333 EnterCriticalSection(This
->crst
);
334 while(This
->nbuffers
--)
335 DS8Buffer_Destroy(This
->buffers
[This
->nbuffers
]);
336 LeaveCriticalSection(This
->crst
);
338 HeapFree(GetProcessHeap(), 0, This
->notifies
);
339 HeapFree(GetProcessHeap(), 0, This
->buffers
);
340 memset(This
, 0, sizeof(*This
));
343 static inline DS8Primary
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
345 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSoundBuffer_iface
);
348 static HRESULT WINAPI
DS8Primary_QueryInterface(IDirectSoundBuffer
*iface
, REFIID riid
, LPVOID
*ppv
)
350 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
352 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
355 if(IsEqualIID(riid
, &IID_IUnknown
) ||
356 IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
357 *ppv
= &This
->IDirectSoundBuffer_iface
;
358 else if(IsEqualIID(riid
, &IID_IDirectSound3DListener
))
360 if((This
->flags
&DSBCAPS_CTRL3D
))
361 *ppv
= &This
->IDirectSound3DListener_iface
;
364 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
368 IUnknown_AddRef((IUnknown
*)*ppv
);
372 return E_NOINTERFACE
;
375 static ULONG WINAPI
DS8Primary_AddRef(IDirectSoundBuffer
*iface
)
377 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
380 ret
= InterlockedIncrement(&This
->ref
);
381 if(ret
== 1) This
->flags
= 0;
386 static ULONG WINAPI
DS8Primary_Release(IDirectSoundBuffer
*iface
)
388 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
391 ret
= InterlockedDecrement(&This
->ref
);
396 static HRESULT WINAPI
DS8Primary_GetCaps(IDirectSoundBuffer
*iface
, DSBCAPS
*caps
)
398 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
400 TRACE("(%p)->(%p)\n", iface
, caps
);
402 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
404 WARN("Invalid DSBCAPS (%p, %"LONGFMT
"u)\n", caps
, caps
? caps
->dwSize
: 0);
405 return DSERR_INVALIDPARAM
;
408 EnterCriticalSection(This
->crst
);
409 caps
->dwFlags
= This
->flags
;
410 caps
->dwBufferBytes
= This
->buf_size
;
411 caps
->dwUnlockTransferRate
= 0;
412 caps
->dwPlayCpuOverhead
= 0;
413 LeaveCriticalSection(This
->crst
);
418 static HRESULT WINAPI
DS8Primary_GetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD
*playpos
, DWORD
*curpos
)
420 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
421 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
423 EnterCriticalSection(This
->crst
);
425 hr
= IDirectSoundBuffer8_GetCurrentPosition(This
->write_emu
, playpos
, curpos
);
426 LeaveCriticalSection(This
->crst
);
431 static HRESULT WINAPI
DS8Primary_GetFormat(IDirectSoundBuffer
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
433 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
439 WARN("Cannot report format or format size\n");
440 return DSERR_INVALIDPARAM
;
443 EnterCriticalSection(This
->crst
);
444 size
= sizeof(This
->format
.Format
) + This
->format
.Format
.cbSize
;
450 hr
= DSERR_INVALIDPARAM
;
452 memcpy(wfx
, &This
->format
.Format
, size
);
454 LeaveCriticalSection(This
->crst
);
459 static HRESULT WINAPI
DS8Primary_GetVolume(IDirectSoundBuffer
*iface
, LONG
*volume
)
461 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
464 TRACE("(%p)->(%p)\n", iface
, volume
);
467 return DSERR_INVALIDPARAM
;
469 EnterCriticalSection(This
->crst
);
470 if(!(This
->flags
& DSBCAPS_CTRLVOLUME
))
471 hr
= DSERR_CONTROLUNAVAIL
;
476 setALContext(This
->ctx
);
477 alGetListenerf(AL_GAIN
, &gain
);
481 *volume
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
483 LeaveCriticalSection(This
->crst
);
488 static HRESULT WINAPI
DS8Primary_GetPan(IDirectSoundBuffer
*iface
, LONG
*pan
)
490 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
493 WARN("(%p)->(%p): semi-stub\n", iface
, pan
);
496 return DSERR_INVALIDPARAM
;
498 EnterCriticalSection(This
->crst
);
500 hr
= IDirectSoundBuffer8_GetPan(This
->write_emu
, pan
);
501 else if(!(This
->flags
& DSBCAPS_CTRLPAN
))
502 hr
= DSERR_CONTROLUNAVAIL
;
505 LeaveCriticalSection(This
->crst
);
510 static HRESULT WINAPI
DS8Primary_GetFrequency(IDirectSoundBuffer
*iface
, DWORD
*freq
)
512 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
515 WARN("(%p)->(%p): semi-stub\n", iface
, freq
);
518 return DSERR_INVALIDPARAM
;
520 EnterCriticalSection(This
->crst
);
521 if(!(This
->flags
& DSBCAPS_CTRLFREQUENCY
))
522 hr
= DSERR_CONTROLUNAVAIL
;
524 *freq
= This
->format
.Format
.nSamplesPerSec
;
525 LeaveCriticalSection(This
->crst
);
530 static HRESULT WINAPI
DS8Primary_GetStatus(IDirectSoundBuffer
*iface
, DWORD
*status
)
532 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
534 TRACE("(%p)->(%p)\n", iface
, status
);
537 return DSERR_INVALIDPARAM
;
539 EnterCriticalSection(This
->crst
);
541 *status
= DSBSTATUS_PLAYING
|DSBSTATUS_LOOPING
;
542 if((This
->flags
&DSBCAPS_LOCDEFER
))
543 *status
|= DSBSTATUS_LOCHARDWARE
;
550 for(i
= 0;i
< This
->nbuffers
;++i
)
552 hr
= IDirectSoundBuffer8_GetStatus(&This
->buffers
[i
]->IDirectSoundBuffer8_iface
, &state
);
553 if(SUCCEEDED(hr
) && (state
&DSBSTATUS_PLAYING
))
556 if(i
== This
->nbuffers
)
558 /* Primary stopped and no buffers playing.. */
563 LeaveCriticalSection(This
->crst
);
568 static HRESULT WINAPI
DS8Primary_Initialize(IDirectSoundBuffer
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
570 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
573 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
575 if(!desc
|| desc
->lpwfxFormat
|| desc
->dwBufferBytes
)
577 WARN("Bad DSBDESC for primary buffer\n");
578 return DSERR_INVALIDPARAM
;
580 if((desc
->dwFlags
&DSBCAPS_CTRLFX
) ||
581 (desc
->dwFlags
&DSBCAPS_CTRLPOSITIONNOTIFY
) ||
582 (desc
->dwFlags
&DSBCAPS_LOCSOFTWARE
))
584 WARN("Bad dwFlags %08"LONGFMT
"x\n", desc
->dwFlags
);
585 return DSERR_INVALIDPARAM
;
588 EnterCriticalSection(This
->crst
);
589 /* Should be 0 if not initialized */
592 hr
= DSERR_ALREADYINITIALIZED
;
596 if(This
->parent
->prio_level
== DSSCL_WRITEPRIMARY
)
598 DSBUFFERDESC emudesc
;
603 ERR("There shouldn't be a write_emu!\n");
604 IDirectSoundBuffer8_Release(This
->write_emu
);
605 This
->write_emu
= NULL
;
608 memset(&emudesc
, 0, sizeof(emudesc
));
609 emudesc
.dwSize
= sizeof(emudesc
);
610 emudesc
.dwFlags
= DSBCAPS_LOCHARDWARE
| (desc
->dwFlags
&DSBCAPS_CTRLPAN
);
611 /* Dont play last incomplete sample */
612 emudesc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
%This
->format
.Format
.nBlockAlign
);
613 emudesc
.lpwfxFormat
= &This
->format
.Format
;
615 hr
= DS8Buffer_Create(&emu
, This
, NULL
);
618 This
->write_emu
= &emu
->IDirectSoundBuffer8_iface
;
619 hr
= IDirectSoundBuffer8_Initialize(This
->write_emu
, ds
, &emudesc
);
622 IDirectSoundBuffer8_Release(This
->write_emu
);
623 This
->write_emu
= NULL
;
629 This
->flags
= desc
->dwFlags
| DSBCAPS_LOCHARDWARE
;
631 LeaveCriticalSection(This
->crst
);
635 static HRESULT WINAPI
DS8Primary_Lock(IDirectSoundBuffer
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
637 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
638 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
640 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %p, %p, %p, %p, %"LONGFMT
"u)\n", iface
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
642 EnterCriticalSection(This
->crst
);
644 hr
= IDirectSoundBuffer8_Lock(This
->write_emu
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
645 LeaveCriticalSection(This
->crst
);
650 static HRESULT WINAPI
DS8Primary_Play(IDirectSoundBuffer
*iface
, DWORD res1
, DWORD res2
, DWORD flags
)
652 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
655 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %"LONGFMT
"u)\n", iface
, res1
, res2
, flags
);
657 if(!(flags
& DSBPLAY_LOOPING
))
659 WARN("Flags (%08"LONGFMT
"x) not set to DSBPLAY_LOOPING\n", flags
);
660 return DSERR_INVALIDPARAM
;
663 EnterCriticalSection(This
->crst
);
666 hr
= IDirectSoundBuffer8_Play(This
->write_emu
, res1
, res2
, flags
);
668 This
->stopped
= FALSE
;
669 LeaveCriticalSection(This
->crst
);
674 static HRESULT WINAPI
DS8Primary_SetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD pos
)
676 WARN("(%p)->(%"LONGFMT
"u)\n", iface
, pos
);
677 return DSERR_INVALIDCALL
;
680 /* Just assume the format is crap, and clean up the damage */
681 static void copy_waveformat(WAVEFORMATEX
*wfx
, const WAVEFORMATEX
*from
)
683 if(from
->wFormatTag
== WAVE_FORMAT_PCM
)
686 if(from
->wBitsPerSample
== 8 ||
687 from
->wBitsPerSample
== 16 ||
688 from
->wBitsPerSample
== 24 ||
689 from
->wBitsPerSample
== 32)
690 wfx
->wBitsPerSample
= from
->wBitsPerSample
;
692 else if(from
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
694 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)wfx
;
695 const WAVEFORMATEXTENSIBLE
*fromx
= (const WAVEFORMATEXTENSIBLE
*)from
;
696 DWORD size
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
698 /* Fail silently.. */
699 if(from
->cbSize
< size
)
701 if(!fromx
->Samples
.wValidBitsPerSample
&&
702 !fromx
->Format
.wBitsPerSample
)
705 if(!IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
706 !IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
708 ERR("Unhandled extensible format: %s\n", debugstr_guid(&wfe
->SubFormat
));
712 wfe
->Format
.wBitsPerSample
= from
->wBitsPerSample
;
713 wfe
->Samples
.wValidBitsPerSample
= fromx
->Samples
.wValidBitsPerSample
;
714 if(!wfe
->Samples
.wValidBitsPerSample
)
715 wfe
->Samples
.wValidBitsPerSample
= wfe
->Format
.wBitsPerSample
;
716 wfe
->Format
.cbSize
= size
;
717 wfe
->dwChannelMask
= fromx
->dwChannelMask
;
718 wfe
->SubFormat
= fromx
->SubFormat
;
722 ERR("Unhandled format tag %04x\n", from
->wFormatTag
);
727 wfx
->nChannels
= from
->nChannels
;
728 wfx
->wFormatTag
= from
->wFormatTag
;
729 if(from
->nSamplesPerSec
>= DSBFREQUENCY_MIN
&&
730 from
->nSamplesPerSec
<= DSBFREQUENCY_MAX
)
731 wfx
->nSamplesPerSec
= from
->nSamplesPerSec
;
732 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
733 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
736 static HRESULT WINAPI
DS8Primary_SetFormat(IDirectSoundBuffer
*iface
, const WAVEFORMATEX
*wfx
)
738 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
742 TRACE("(%p)->(%p)\n", iface
, wfx
);
746 WARN("Missing format\n");
747 return DSERR_INVALIDPARAM
;
750 EnterCriticalSection(This
->crst
);
752 if(This
->parent
->prio_level
< DSSCL_PRIORITY
)
754 hr
= DSERR_PRIOLEVELNEEDED
;
758 TRACE("Requested primary format:\n"
759 " FormatTag = %04x\n"
761 " SamplesPerSec = %"LONGFMT
"u\n"
762 " AvgBytesPerSec = %"LONGFMT
"u\n"
764 " BitsPerSample = %u\n",
765 wfx
->wFormatTag
, wfx
->nChannels
,
766 wfx
->nSamplesPerSec
, wfx
->nAvgBytesPerSec
,
767 wfx
->nBlockAlign
, wfx
->wBitsPerSample
);
769 copy_waveformat(&This
->format
.Format
, wfx
);
771 freq
= This
->format
.Format
.nSamplesPerSec
;
772 alcGetIntegerv(This
->parent
->device
, ALC_FREQUENCY
, 1, &freq
);
773 checkALCError(This
->parent
->device
);
775 This
->format
.Format
.nSamplesPerSec
= freq
;
776 This
->format
.Format
.nAvgBytesPerSec
= This
->format
.Format
.nBlockAlign
*
777 This
->format
.Format
.nSamplesPerSec
;
784 memset(&desc
, 0, sizeof(desc
));
785 desc
.dwSize
= sizeof(desc
);
786 desc
.dwFlags
= DSBCAPS_LOCHARDWARE
|DSBCAPS_CTRLPAN
;
787 desc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
% This
->format
.Format
.nBlockAlign
);
788 desc
.lpwfxFormat
= &This
->format
.Format
;
790 hr
= DS8Buffer_Create(&buf
, This
, NULL
);
794 hr
= IDirectSoundBuffer8_Initialize(&buf
->IDirectSoundBuffer8_iface
, &This
->parent
->IDirectSound_iface
, &desc
);
796 DS8Buffer_Destroy(buf
);
799 IDirectSoundBuffer8_Release(This
->write_emu
);
800 This
->write_emu
= &buf
->IDirectSoundBuffer8_iface
;
805 LeaveCriticalSection(This
->crst
);
809 static HRESULT WINAPI
DS8Primary_SetVolume(IDirectSoundBuffer
*iface
, LONG vol
)
811 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
814 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, vol
);
816 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
818 WARN("Invalid volume (%"LONGFMT
"d)\n", vol
);
819 return DSERR_INVALIDPARAM
;
822 EnterCriticalSection(This
->crst
);
823 if(!(This
->flags
&DSBCAPS_CTRLVOLUME
))
824 hr
= DSERR_CONTROLUNAVAIL
;
827 setALContext(This
->ctx
);
828 alListenerf(AL_GAIN
, mB_to_gain(vol
));
831 LeaveCriticalSection(This
->crst
);
836 static HRESULT WINAPI
DS8Primary_SetPan(IDirectSoundBuffer
*iface
, LONG pan
)
838 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
841 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, pan
);
843 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
845 WARN("invalid parameter: pan = %"LONGFMT
"d\n", pan
);
846 return DSERR_INVALIDPARAM
;
849 EnterCriticalSection(This
->crst
);
850 if(!(This
->flags
&DSBCAPS_CTRLPAN
))
852 WARN("control unavailable\n");
853 hr
= DSERR_CONTROLUNAVAIL
;
855 else if(This
->write_emu
)
856 hr
= IDirectSoundBuffer8_SetPan(This
->write_emu
, pan
);
859 FIXME("Not supported\n");
862 LeaveCriticalSection(This
->crst
);
867 static HRESULT WINAPI
DS8Primary_SetFrequency(IDirectSoundBuffer
*iface
, DWORD freq
)
869 WARN("(%p)->(%"LONGFMT
"u)\n", iface
, freq
);
870 return DSERR_CONTROLUNAVAIL
;
873 static HRESULT WINAPI
DS8Primary_Stop(IDirectSoundBuffer
*iface
)
875 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
878 TRACE("(%p)->()\n", iface
);
880 EnterCriticalSection(This
->crst
);
882 hr
= IDirectSoundBuffer8_Stop(This
->write_emu
);
884 This
->stopped
= TRUE
;
885 LeaveCriticalSection(This
->crst
);
890 static HRESULT WINAPI
DS8Primary_Unlock(IDirectSoundBuffer
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
892 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
893 HRESULT hr
= DSERR_INVALIDCALL
;
895 TRACE("(%p)->(%p, %"LONGFMT
"u, %p, %"LONGFMT
"u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
897 EnterCriticalSection(This
->crst
);
899 hr
= IDirectSoundBuffer8_Unlock(This
->write_emu
, ptr1
, len1
, ptr2
, len2
);
900 LeaveCriticalSection(This
->crst
);
905 static HRESULT WINAPI
DS8Primary_Restore(IDirectSoundBuffer
*iface
)
907 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
910 TRACE("(%p)->()\n", iface
);
912 EnterCriticalSection(This
->crst
);
914 hr
= IDirectSoundBuffer8_Restore(This
->write_emu
);
915 LeaveCriticalSection(This
->crst
);
920 static const IDirectSoundBufferVtbl DS8Primary_Vtbl
=
922 DS8Primary_QueryInterface
,
926 DS8Primary_GetCurrentPosition
,
927 DS8Primary_GetFormat
,
928 DS8Primary_GetVolume
,
930 DS8Primary_GetFrequency
,
931 DS8Primary_GetStatus
,
932 DS8Primary_Initialize
,
935 DS8Primary_SetCurrentPosition
,
936 DS8Primary_SetFormat
,
937 DS8Primary_SetVolume
,
939 DS8Primary_SetFrequency
,
945 static inline DS8Primary
*impl_from_IDirectSound3DListener(IDirectSound3DListener
*iface
)
947 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSound3DListener_iface
);
950 static HRESULT WINAPI
DS8Primary3D_QueryInterface(IDirectSound3DListener
*iface
, REFIID riid
, void **ppv
)
952 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
953 return DS8Primary_QueryInterface(&This
->IDirectSoundBuffer_iface
, riid
, ppv
);
956 static ULONG WINAPI
DS8Primary3D_AddRef(IDirectSound3DListener
*iface
)
958 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
961 ret
= InterlockedIncrement(&This
->ds3d_ref
);
962 TRACE("new refcount %"LONGFMT
"d\n", ret
);
968 /* Considering the primary buffer doesn't get destroyed
969 * it doesn't make sense to destroy ds3d here
971 static ULONG WINAPI
DS8Primary3D_Release(IDirectSound3DListener
*iface
)
973 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
976 ret
= InterlockedDecrement(&This
->ds3d_ref
);
977 TRACE("new refcount %"LONGFMT
"d\n", ret
);
983 static HRESULT WINAPI
DS8Primary3D_GetAllParameters(IDirectSound3DListener
*iface
, DS3DLISTENER
*listener
)
985 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
987 TRACE("(%p)->(%p)\n", iface
, listener
);
989 if(!listener
|| listener
->dwSize
< sizeof(*listener
))
991 WARN("Invalid DS3DLISTENER %p %"LONGFMT
"u\n", listener
, listener
? listener
->dwSize
: 0);
992 return DSERR_INVALIDPARAM
;
995 EnterCriticalSection(This
->crst
);
996 setALContext(This
->ctx
);
997 IDirectSound3DListener_GetPosition(iface
, &listener
->vPosition
);
998 IDirectSound3DListener_GetVelocity(iface
, &listener
->vVelocity
);
999 IDirectSound3DListener_GetOrientation(iface
, &listener
->vOrientFront
, &listener
->vOrientTop
);
1000 IDirectSound3DListener_GetDistanceFactor(iface
, &listener
->flDistanceFactor
);
1001 IDirectSound3DListener_GetRolloffFactor(iface
, &listener
->flRolloffFactor
);
1002 IDirectSound3DListener_GetRolloffFactor(iface
, &listener
->flDopplerFactor
);
1004 LeaveCriticalSection(This
->crst
);
1009 static HRESULT WINAPI
DS8Primary3D_GetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE
*distancefactor
)
1011 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1013 TRACE("(%p)->(%p)\n", iface
, distancefactor
);
1017 WARN("Invalid parameter %p\n", distancefactor
);
1018 return DSERR_INVALIDPARAM
;
1021 EnterCriticalSection(This
->crst
);
1022 setALContext(This
->ctx
);
1024 *distancefactor
= 343.3f
/alGetFloat(AL_SPEED_OF_SOUND
);
1028 LeaveCriticalSection(This
->crst
);
1033 static HRESULT WINAPI
DS8Primary3D_GetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE
*dopplerfactor
)
1035 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1037 TRACE("(%p)->(%p)\n", iface
, dopplerfactor
);
1041 WARN("Invalid parameter %p\n", dopplerfactor
);
1042 return DSERR_INVALIDPARAM
;
1045 EnterCriticalSection(This
->crst
);
1046 setALContext(This
->ctx
);
1048 *dopplerfactor
= alGetFloat(AL_DOPPLER_FACTOR
);
1052 LeaveCriticalSection(This
->crst
);
1057 static HRESULT WINAPI
DS8Primary3D_GetOrientation(IDirectSound3DListener
*iface
, D3DVECTOR
*front
, D3DVECTOR
*top
)
1059 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1062 TRACE("(%p)->(%p, %p)\n", iface
, front
, top
);
1066 WARN("Invalid parameter %p %p\n", front
, top
);
1067 return DSERR_INVALIDPARAM
;
1070 EnterCriticalSection(This
->crst
);
1071 setALContext(This
->ctx
);
1073 alGetListenerfv(AL_ORIENTATION
, orient
);
1076 front
->x
= orient
[0];
1077 front
->y
= orient
[1];
1078 front
->z
= -orient
[2];
1081 top
->z
= -orient
[5];
1084 LeaveCriticalSection(This
->crst
);
1089 static HRESULT WINAPI
DS8Primary3D_GetPosition(IDirectSound3DListener
*iface
, D3DVECTOR
*pos
)
1091 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1094 TRACE("(%p)->(%p)\n", iface
, pos
);
1098 WARN("Invalid parameter %p\n", pos
);
1099 return DSERR_INVALIDPARAM
;
1102 EnterCriticalSection(This
->crst
);
1103 setALContext(This
->ctx
);
1105 alGetListenerfv(AL_POSITION
, alpos
);
1113 LeaveCriticalSection(This
->crst
);
1118 static HRESULT WINAPI
DS8Primary3D_GetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE
*rollofffactor
)
1120 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1122 TRACE("(%p)->(%p)\n", iface
, rollofffactor
);
1126 WARN("Invalid parameter %p\n", rollofffactor
);
1127 return DSERR_INVALIDPARAM
;
1130 EnterCriticalSection(This
->crst
);
1131 *rollofffactor
= This
->rollofffactor
;
1132 LeaveCriticalSection(This
->crst
);
1137 static HRESULT WINAPI
DS8Primary3D_GetVelocity(IDirectSound3DListener
*iface
, D3DVECTOR
*velocity
)
1139 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1142 TRACE("(%p)->(%p)\n", iface
, velocity
);
1146 WARN("Invalid parameter %p\n", velocity
);
1147 return DSERR_INVALIDPARAM
;
1150 EnterCriticalSection(This
->crst
);
1151 setALContext(This
->ctx
);
1153 alGetListenerfv(AL_VELOCITY
, vel
);
1156 velocity
->x
= vel
[0];
1157 velocity
->y
= vel
[1];
1158 velocity
->z
= -vel
[2];
1161 LeaveCriticalSection(This
->crst
);
1166 static HRESULT WINAPI
DS8Primary3D_SetAllParameters(IDirectSound3DListener
*iface
, const DS3DLISTENER
*listen
, DWORD apply
)
1168 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1170 TRACE("(%p)->(%p, %"LONGFMT
"u)\n", iface
, listen
, apply
);
1172 if(!listen
|| listen
->dwSize
< sizeof(*listen
))
1174 WARN("Invalid parameter %p %"LONGFMT
"u\n", listen
, listen
? listen
->dwSize
: 0);
1175 return DSERR_INVALIDPARAM
;
1178 if(listen
->flDistanceFactor
> DS3D_MAXDISTANCEFACTOR
||
1179 listen
->flDistanceFactor
< DS3D_MINDISTANCEFACTOR
)
1181 WARN("Invalid distance factor (%f)\n", listen
->flDistanceFactor
);
1182 return DSERR_INVALIDPARAM
;
1185 if(listen
->flDopplerFactor
> DS3D_MAXDOPPLERFACTOR
||
1186 listen
->flDopplerFactor
< DS3D_MINDOPPLERFACTOR
)
1188 WARN("Invalid doppler factor (%f)\n", listen
->flDopplerFactor
);
1189 return DSERR_INVALIDPARAM
;
1192 if(listen
->flRolloffFactor
< DS3D_MINROLLOFFFACTOR
||
1193 listen
->flRolloffFactor
> DS3D_MAXROLLOFFFACTOR
)
1195 WARN("Invalid rolloff factor (%f)\n", listen
->flRolloffFactor
);
1196 return DSERR_INVALIDPARAM
;
1199 EnterCriticalSection(This
->crst
);
1200 setALContext(This
->ctx
);
1201 IDirectSound3DListener_SetPosition(iface
, listen
->vPosition
.x
, listen
->vPosition
.y
, listen
->vPosition
.z
, apply
);
1202 IDirectSound3DListener_SetVelocity(iface
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, listen
->vVelocity
.z
, apply
);
1203 IDirectSound3DListener_SetOrientation(iface
, listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, listen
->vOrientFront
.z
,
1204 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, listen
->vOrientTop
.z
, apply
);
1205 IDirectSound3DListener_SetDistanceFactor(iface
, listen
->flDistanceFactor
, apply
);
1206 IDirectSound3DListener_SetRolloffFactor(iface
, listen
->flRolloffFactor
, apply
);
1207 IDirectSound3DListener_SetDopplerFactor(iface
, listen
->flDopplerFactor
, apply
);
1209 LeaveCriticalSection(This
->crst
);
1214 static HRESULT WINAPI
DS8Primary3D_SetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1216 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1218 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", iface
, factor
, apply
);
1220 if(factor
< DS3D_MINDISTANCEFACTOR
||
1221 factor
> DS3D_MAXDISTANCEFACTOR
)
1223 WARN("Invalid parameter %f\n", factor
);
1224 return DSERR_INVALIDPARAM
;
1227 EnterCriticalSection(This
->crst
);
1228 if(apply
== DS3D_DEFERRED
)
1230 This
->listen
.flDistanceFactor
= factor
;
1231 This
->dirty
.bit
.distancefactor
= 1;
1235 setALContext(This
->ctx
);
1236 alSpeedOfSound(343.3f
/factor
);
1237 if(This
->SupportedExt
[EXT_EFX
])
1238 alListenerf(AL_METERS_PER_UNIT
, factor
);
1242 LeaveCriticalSection(This
->crst
);
1247 static HRESULT WINAPI
DS8Primary3D_SetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1249 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1251 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", iface
, factor
, apply
);
1253 if(factor
< DS3D_MINDOPPLERFACTOR
||
1254 factor
> DS3D_MAXDOPPLERFACTOR
)
1256 WARN("Invalid parameter %f\n", factor
);
1257 return DSERR_INVALIDPARAM
;
1260 EnterCriticalSection(This
->crst
);
1261 if(apply
== DS3D_DEFERRED
)
1263 This
->listen
.flDopplerFactor
= factor
;
1264 This
->dirty
.bit
.dopplerfactor
= 1;
1268 setALContext(This
->ctx
);
1269 alDopplerFactor(factor
);
1273 LeaveCriticalSection(This
->crst
);
1278 static HRESULT WINAPI
DS8Primary3D_SetOrientation(IDirectSound3DListener
*iface
, D3DVALUE xFront
, D3DVALUE yFront
, D3DVALUE zFront
, D3DVALUE xTop
, D3DVALUE yTop
, D3DVALUE zTop
, DWORD apply
)
1280 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1282 TRACE("(%p)->(%f, %f, %f, %f, %f, %f, %"LONGFMT
"u)\n", iface
, xFront
, yFront
, zFront
, xTop
, yTop
, zTop
, apply
);
1284 EnterCriticalSection(This
->crst
);
1285 if(apply
== DS3D_DEFERRED
)
1287 This
->listen
.vOrientFront
.x
= xFront
;
1288 This
->listen
.vOrientFront
.y
= yFront
;
1289 This
->listen
.vOrientFront
.z
= zFront
;
1290 This
->listen
.vOrientTop
.x
= xTop
;
1291 This
->listen
.vOrientTop
.y
= yTop
;
1292 This
->listen
.vOrientTop
.z
= zTop
;
1293 This
->dirty
.bit
.orientation
= 1;
1297 ALfloat orient
[6] = {
1298 xFront
, yFront
, -zFront
,
1301 setALContext(This
->ctx
);
1302 alListenerfv(AL_ORIENTATION
, orient
);
1306 LeaveCriticalSection(This
->crst
);
1311 static HRESULT WINAPI
DS8Primary3D_SetPosition(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1313 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1315 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", iface
, x
, y
, z
, apply
);
1317 EnterCriticalSection(This
->crst
);
1318 if(apply
== DS3D_DEFERRED
)
1320 This
->listen
.vPosition
.x
= x
;
1321 This
->listen
.vPosition
.y
= y
;
1322 This
->listen
.vPosition
.z
= z
;
1323 This
->dirty
.bit
.pos
= 1;
1327 setALContext(This
->ctx
);
1328 alListener3f(AL_POSITION
, x
, y
, -z
);
1332 LeaveCriticalSection(This
->crst
);
1337 static HRESULT WINAPI
DS8Primary3D_SetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1339 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1341 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", iface
, factor
, apply
);
1343 if(factor
< DS3D_MINROLLOFFFACTOR
||
1344 factor
> DS3D_MAXROLLOFFFACTOR
)
1346 WARN("Invalid parameter %f\n", factor
);
1347 return DSERR_INVALIDPARAM
;
1350 EnterCriticalSection(This
->crst
);
1351 if(apply
== DS3D_DEFERRED
)
1353 This
->listen
.flRolloffFactor
= factor
;
1354 This
->dirty
.bit
.rollofffactor
= 1;
1360 setALContext(This
->ctx
);
1361 for(i
= 0;i
< This
->nbuffers
;++i
)
1363 if(This
->buffers
[i
]->ds3dmode
!= DS3DMODE_DISABLE
)
1364 alSourcef(This
->buffers
[i
]->source
, AL_ROLLOFF_FACTOR
, factor
);
1369 This
->rollofffactor
= factor
;
1371 LeaveCriticalSection(This
->crst
);
1376 static HRESULT WINAPI
DS8Primary3D_SetVelocity(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1378 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1380 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", iface
, x
, y
, z
, apply
);
1382 EnterCriticalSection(This
->crst
);
1383 if(apply
== DS3D_DEFERRED
)
1385 This
->listen
.vVelocity
.x
= x
;
1386 This
->listen
.vVelocity
.y
= y
;
1387 This
->listen
.vVelocity
.z
= z
;
1388 This
->dirty
.bit
.vel
= 1;
1392 setALContext(This
->ctx
);
1393 alListener3f(AL_VELOCITY
, x
, y
, -z
);
1397 LeaveCriticalSection(This
->crst
);
1402 static HRESULT WINAPI
DS8Primary3D_CommitDeferredSettings(IDirectSound3DListener
*iface
)
1404 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1405 const DS3DLISTENER
*listen
= &This
->listen
;
1408 EnterCriticalSection(This
->crst
);
1409 setALContext(This
->ctx
);
1410 This
->DeferUpdates();
1412 if(This
->dirty
.bit
.pos
)
1413 alListener3f(AL_POSITION
, listen
->vPosition
.x
, listen
->vPosition
.y
, -listen
->vPosition
.z
);
1414 if(This
->dirty
.bit
.vel
)
1415 alListener3f(AL_VELOCITY
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, -listen
->vVelocity
.z
);
1416 if(This
->dirty
.bit
.orientation
)
1418 ALfloat orient
[6] = {
1419 listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, -listen
->vOrientFront
.z
,
1420 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, -listen
->vOrientTop
.z
1422 alListenerfv(AL_ORIENTATION
, orient
);
1424 if(This
->dirty
.bit
.distancefactor
)
1426 alSpeedOfSound(343.3f
/listen
->flDistanceFactor
);
1427 if(This
->SupportedExt
[EXT_EFX
])
1428 alListenerf(AL_METERS_PER_UNIT
, listen
->flDistanceFactor
);
1431 if(This
->dirty
.bit
.rollofffactor
)
1433 ALfloat rolloff
= This
->rollofffactor
;
1434 for(i
= 0;i
< This
->nbuffers
;++i
)
1436 DS8Buffer
*buf
= This
->buffers
[i
];
1437 if(buf
->ds3dmode
!= DS3DMODE_DISABLE
)
1438 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
, rolloff
);
1442 if(This
->dirty
.bit
.dopplerfactor
)
1443 alDopplerFactor(listen
->flDopplerFactor
);
1445 if(This
->dirty
.bit
.effect
)
1446 This
->ExtAL
->AuxiliaryEffectSloti(This
->auxslot
, AL_EFFECTSLOT_EFFECT
, This
->effect
);
1448 /* checkALError is here for debugging */
1451 TRACE("Dirty flags was: 0x%02x\n", This
->dirty
.flags
);
1452 This
->dirty
.flags
= 0;
1454 for(i
= 0;i
< This
->nbuffers
;++i
)
1456 DS8Buffer
*buf
= This
->buffers
[i
];
1458 if(!buf
->dirty
.flags
)
1461 if(buf
->dirty
.bit
.pos
)
1462 alSource3f(buf
->source
, AL_POSITION
,
1463 buf
->ds3dbuffer
.vPosition
.x
,
1464 buf
->ds3dbuffer
.vPosition
.y
,
1465 -buf
->ds3dbuffer
.vPosition
.z
);
1466 if(buf
->dirty
.bit
.vel
)
1467 alSource3f(buf
->source
, AL_VELOCITY
,
1468 buf
->ds3dbuffer
.vVelocity
.x
,
1469 buf
->ds3dbuffer
.vVelocity
.y
,
1470 -buf
->ds3dbuffer
.vVelocity
.z
);
1471 if(buf
->dirty
.bit
.cone_angles
)
1473 alSourcei(buf
->source
, AL_CONE_INNER_ANGLE
,
1474 buf
->ds3dbuffer
.dwInsideConeAngle
);
1475 alSourcei(buf
->source
, AL_CONE_OUTER_ANGLE
,
1476 buf
->ds3dbuffer
.dwOutsideConeAngle
);
1478 if(buf
->dirty
.bit
.cone_orient
)
1479 alSource3f(buf
->source
, AL_DIRECTION
,
1480 buf
->ds3dbuffer
.vConeOrientation
.x
,
1481 buf
->ds3dbuffer
.vConeOrientation
.y
,
1482 -buf
->ds3dbuffer
.vConeOrientation
.z
);
1483 if(buf
->dirty
.bit
.cone_outsidevolume
)
1484 alSourcef(buf
->source
, AL_CONE_OUTER_GAIN
,
1485 mB_to_gain(buf
->ds3dbuffer
.lConeOutsideVolume
));
1486 if(buf
->dirty
.bit
.min_distance
)
1487 alSourcef(buf
->source
, AL_REFERENCE_DISTANCE
, buf
->ds3dbuffer
.flMinDistance
);
1488 if(buf
->dirty
.bit
.max_distance
)
1489 alSourcef(buf
->source
, AL_MAX_DISTANCE
, buf
->ds3dbuffer
.flMaxDistance
);
1490 if(buf
->dirty
.bit
.mode
)
1492 buf
->ds3dmode
= buf
->ds3dbuffer
.dwMode
;
1493 alSourcei(buf
->source
, AL_SOURCE_RELATIVE
,
1494 (buf
->ds3dmode
!=DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
1495 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
,
1496 (buf
->ds3dmode
==DS3DMODE_DISABLE
) ? 0.0f
: This
->rollofffactor
);
1498 buf
->dirty
.flags
= 0;
1502 This
->ProcessUpdates();
1504 LeaveCriticalSection(This
->crst
);
1509 static const IDirectSound3DListenerVtbl DS8Primary3D_Vtbl
=
1511 DS8Primary3D_QueryInterface
,
1512 DS8Primary3D_AddRef
,
1513 DS8Primary3D_Release
,
1514 DS8Primary3D_GetAllParameters
,
1515 DS8Primary3D_GetDistanceFactor
,
1516 DS8Primary3D_GetDopplerFactor
,
1517 DS8Primary3D_GetOrientation
,
1518 DS8Primary3D_GetPosition
,
1519 DS8Primary3D_GetRolloffFactor
,
1520 DS8Primary3D_GetVelocity
,
1521 DS8Primary3D_SetAllParameters
,
1522 DS8Primary3D_SetDistanceFactor
,
1523 DS8Primary3D_SetDopplerFactor
,
1524 DS8Primary3D_SetOrientation
,
1525 DS8Primary3D_SetPosition
,
1526 DS8Primary3D_SetRolloffFactor
,
1527 DS8Primary3D_SetVelocity
,
1528 DS8Primary3D_CommitDeferredSettings
1531 /* NOTE: Although the app handles listener properties through secondary buffers,
1532 * we pass the requests to the primary buffer though a propertyset interface.
1533 * These methods are not exposed to the app. */
1534 static inline DS8Primary
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
1536 return CONTAINING_RECORD(iface
, DS8Primary
, IKsPropertySet_iface
);
1539 static HRESULT WINAPI
DS8PrimaryProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
1541 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1542 return DS8Primary_QueryInterface(&This
->IDirectSoundBuffer_iface
, riid
, ppv
);
1545 static ULONG WINAPI
DS8PrimaryProp_AddRef(IKsPropertySet
*iface
)
1547 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1550 ret
= InterlockedIncrement(&This
->prop_ref
);
1551 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1556 static ULONG WINAPI
DS8PrimaryProp_Release(IKsPropertySet
*iface
)
1558 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1561 ret
= InterlockedDecrement(&This
->prop_ref
);
1562 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1567 static HRESULT WINAPI
DS8PrimaryProp_Get(IKsPropertySet
*iface
,
1568 REFGUID guidPropSet
, ULONG dwPropID
,
1569 LPVOID pInstanceData
, ULONG cbInstanceData
,
1570 LPVOID pPropData
, ULONG cbPropData
,
1573 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1574 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1575 (void)pInstanceData
;
1576 (void)cbInstanceData
;
1578 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1580 EnterCriticalSection(This
->crst
);
1582 if(This
->effect
== 0)
1583 res
= E_PROP_ID_UNSUPPORTED
;
1584 else switch(dwPropID
)
1586 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
1587 res
= DSERR_INVALIDPARAM
;
1588 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1592 EAXLISTENERPROPERTIES
*props
;
1593 } data
= { pPropData
};
1595 *data
.props
= This
->eax_prop
;
1596 *pcbReturned
= sizeof(EAXLISTENERPROPERTIES
);
1601 case DSPROPERTY_EAXLISTENER_ROOM
:
1602 res
= DSERR_INVALIDPARAM
;
1603 if(cbPropData
>= sizeof(LONG
))
1608 } data
= { pPropData
};
1610 *data
.l
= This
->eax_prop
.lRoom
;
1611 *pcbReturned
= sizeof(LONG
);
1615 case DSPROPERTY_EAXLISTENER_ROOMHF
:
1616 res
= DSERR_INVALIDPARAM
;
1617 if(cbPropData
>= sizeof(LONG
))
1622 } data
= { pPropData
};
1624 *data
.l
= This
->eax_prop
.lRoomHF
;
1625 *pcbReturned
= sizeof(LONG
);
1630 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
1631 res
= DSERR_INVALIDPARAM
;
1632 if(cbPropData
>= sizeof(FLOAT
))
1637 } data
= { pPropData
};
1639 *data
.fl
= This
->eax_prop
.flRoomRolloffFactor
;
1640 *pcbReturned
= sizeof(FLOAT
);
1645 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
1646 res
= DSERR_INVALIDPARAM
;
1647 if(cbPropData
>= sizeof(DWORD
))
1652 } data
= { pPropData
};
1654 *data
.dw
= This
->eax_prop
.dwEnvironment
;
1655 *pcbReturned
= sizeof(DWORD
);
1660 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
1661 res
= DSERR_INVALIDPARAM
;
1662 if(cbPropData
>= sizeof(FLOAT
))
1667 } data
= { pPropData
};
1669 *data
.fl
= This
->eax_prop
.flEnvironmentSize
;
1670 *pcbReturned
= sizeof(FLOAT
);
1674 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
1675 res
= DSERR_INVALIDPARAM
;
1676 if(cbPropData
>= sizeof(FLOAT
))
1681 } data
= { pPropData
};
1683 *data
.fl
= This
->eax_prop
.flEnvironmentDiffusion
;
1684 *pcbReturned
= sizeof(FLOAT
);
1689 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
1690 res
= DSERR_INVALIDPARAM
;
1691 if(cbPropData
>= sizeof(FLOAT
))
1696 } data
= { pPropData
};
1698 *data
.fl
= This
->eax_prop
.flAirAbsorptionHF
;
1699 *pcbReturned
= sizeof(FLOAT
);
1704 case DSPROPERTY_EAXLISTENER_FLAGS
:
1705 res
= DSERR_INVALIDPARAM
;
1706 if(cbPropData
>= sizeof(DWORD
))
1711 } data
= { pPropData
};
1713 *data
.dw
= This
->eax_prop
.dwFlags
;
1714 *pcbReturned
= sizeof(DWORD
);
1720 FIXME("Unhandled propid: 0x%08"LONGFMT
"x\n", dwPropID
);
1724 LeaveCriticalSection(This
->crst
);
1727 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
1732 static HRESULT WINAPI
DS8PrimaryProp_Set(IKsPropertySet
*iface
,
1733 REFGUID guidPropSet
, ULONG dwPropID
,
1734 LPVOID pInstanceData
, ULONG cbInstanceData
,
1735 LPVOID pPropData
, ULONG cbPropData
)
1737 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1738 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1739 (void)pInstanceData
;
1740 (void)cbInstanceData
;
1742 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1744 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXLISTENER_DEFERRED
;
1745 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXLISTENER_DEFERRED
);
1747 EnterCriticalSection(This
->crst
);
1748 setALContext(This
->ctx
);
1750 if(This
->effect
== 0)
1751 res
= E_PROP_ID_UNSUPPORTED
;
1754 case 0: /* 0 = not setting any property, just apply */
1758 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
1760 res
= DSERR_INVALIDPARAM
;
1761 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1765 const EAXLISTENERPROPERTIES
*props
;
1766 } data
= { pPropData
};
1768 /* FIXME: Need to validate property values... Ignore? Clamp? Error? */
1769 This
->eax_prop
= *data
.props
;
1770 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DENSITY
,
1771 (data
.props
->flEnvironmentSize
< 2.0f
) ?
1772 (data
.props
->flEnvironmentSize
- 1.0f
) : 1.0f
);
1773 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
1774 data
.props
->flEnvironmentDiffusion
);
1776 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAIN
,
1777 mB_to_gain(data
.props
->lRoom
));
1778 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAINHF
,
1779 mB_to_gain(data
.props
->lRoomHF
));
1781 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1782 data
.props
->flRoomRolloffFactor
);
1784 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DECAY_TIME
,
1785 data
.props
->flDecayTime
);
1786 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DECAY_HFRATIO
,
1787 data
.props
->flDecayHFRatio
);
1789 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_REFLECTIONS_GAIN
,
1790 mB_to_gain(data
.props
->lReflections
));
1791 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_REFLECTIONS_DELAY
,
1792 data
.props
->flReflectionsDelay
);
1794 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_LATE_REVERB_GAIN
,
1795 mB_to_gain(data
.props
->lReverb
));
1796 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_LATE_REVERB_DELAY
,
1797 data
.props
->flReverbDelay
);
1799 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
1800 mB_to_gain(data
.props
->flAirAbsorptionHF
));
1802 This
->ExtAL
->Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
1803 (data
.props
->dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
1804 AL_TRUE
: AL_FALSE
);
1808 This
->dirty
.bit
.effect
= 1;
1813 case DSPROPERTY_EAXLISTENER_ROOM
:
1814 res
= DSERR_INVALIDPARAM
;
1815 if(cbPropData
>= sizeof(LONG
))
1820 } data
= { pPropData
};
1822 This
->eax_prop
.lRoom
= *data
.l
;
1823 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAIN
,
1824 mB_to_gain(This
->eax_prop
.lRoom
));
1827 This
->dirty
.bit
.effect
= 1;
1831 case DSPROPERTY_EAXLISTENER_ROOMHF
:
1832 res
= DSERR_INVALIDPARAM
;
1833 if(cbPropData
>= sizeof(LONG
))
1838 } data
= { pPropData
};
1840 This
->eax_prop
.lRoomHF
= *data
.l
;
1841 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAINHF
,
1842 mB_to_gain(This
->eax_prop
.lRoomHF
));
1845 This
->dirty
.bit
.effect
= 1;
1850 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
1851 res
= DSERR_INVALIDPARAM
;
1852 if(cbPropData
>= sizeof(FLOAT
))
1857 } data
= { pPropData
};
1859 This
->eax_prop
.flRoomRolloffFactor
= *data
.fl
;
1860 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1861 This
->eax_prop
.flRoomRolloffFactor
);
1864 This
->dirty
.bit
.effect
= 1;
1869 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
1870 res
= DSERR_INVALIDPARAM
;
1871 if(cbPropData
>= sizeof(DWORD
))
1876 } data
= { pPropData
};
1878 if(*data
.dw
< EAX_ENVIRONMENT_COUNT
)
1880 /* Get the environment index's default and pass it down to
1882 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
1883 pPropData
= (void*)&EnvironmentDefaults
[*data
.dw
];
1884 cbPropData
= sizeof(EnvironmentDefaults
[*data
.dw
]);
1890 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
1891 res
= DSERR_INVALIDPARAM
;
1892 if(cbPropData
>= sizeof(FLOAT
))
1897 } data
= { pPropData
};
1899 if(*data
.fl
>= 1.0f
&& *data
.fl
<= 100.0f
)
1901 double scale
= (*data
.fl
)/This
->eax_prop
.flEnvironmentSize
;
1903 This
->eax_prop
.flEnvironmentSize
= *data
.fl
;
1905 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYTIMESCALE
))
1907 This
->eax_prop
.flDecayTime
*= scale
;
1908 This
->eax_prop
.flDecayTime
= clampF(This
->eax_prop
.flDecayTime
, 0.1f
, 20.0f
);
1910 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSSCALE
))
1912 This
->eax_prop
.lReflections
+= gain_to_mB(1.0/scale
);
1913 This
->eax_prop
.lReflections
= clampI(This
->eax_prop
.lReflections
, -10000, 1000);
1915 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE
))
1917 This
->eax_prop
.flReflectionsDelay
*= scale
;
1918 This
->eax_prop
.flReflectionsDelay
= clampF(This
->eax_prop
.flReflectionsDelay
, 0.0f
, 0.3f
);
1920 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBSCALE
))
1922 This
->eax_prop
.lReverb
+= gain_to_mB(1.0/scale
);
1923 This
->eax_prop
.lReverb
= clampI(This
->eax_prop
.lReverb
, -10000, 2000);
1925 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBDELAYSCALE
))
1927 This
->eax_prop
.flReverbDelay
*= scale
;
1928 This
->eax_prop
.flReverbDelay
= clampF(This
->eax_prop
.flReverbDelay
, 0.0f
, 0.1f
);
1931 /* Pass the updated environment properties down to ALLPARAMETERS */
1932 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
1933 pPropData
= (void*)&This
->eax_prop
;
1934 cbPropData
= sizeof(This
->eax_prop
);
1939 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
1940 res
= DSERR_INVALIDPARAM
;
1941 if(cbPropData
>= sizeof(FLOAT
))
1946 } data
= { pPropData
};
1948 This
->eax_prop
.flEnvironmentDiffusion
= *data
.fl
;
1949 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
1950 This
->eax_prop
.flEnvironmentDiffusion
);
1953 This
->dirty
.bit
.effect
= 1;
1958 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
1959 res
= DSERR_INVALIDPARAM
;
1960 if(cbPropData
>= sizeof(FLOAT
))
1965 } data
= { pPropData
};
1967 This
->eax_prop
.flAirAbsorptionHF
= *data
.fl
;
1968 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
1969 mB_to_gain(This
->eax_prop
.flAirAbsorptionHF
));
1972 This
->dirty
.bit
.effect
= 1;
1977 case DSPROPERTY_EAXLISTENER_FLAGS
:
1978 res
= DSERR_INVALIDPARAM
;
1979 if(cbPropData
>= sizeof(DWORD
))
1984 } data
= { pPropData
};
1986 This
->eax_prop
.dwFlags
= *data
.dw
;
1987 This
->ExtAL
->Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
1988 (This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
1989 AL_TRUE
: AL_FALSE
);
1992 This
->dirty
.bit
.effect
= 1;
1996 FIXME("Unhandled propid: 0x%08"LONGFMT
"x\n", propid
);
2000 if(res
== DS_OK
&& immediate
)
2001 IDirectSound3DListener_CommitDeferredSettings(&This
->IDirectSound3DListener_iface
);
2004 LeaveCriticalSection(This
->crst
);
2007 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2012 static HRESULT WINAPI
DS8PrimaryProp_QuerySupport(IKsPropertySet
*iface
,
2013 REFGUID guidPropSet
, ULONG dwPropID
,
2014 PULONG pTypeSupport
)
2016 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
2017 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
2019 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2021 EnterCriticalSection(This
->crst
);
2023 if(This
->effect
== 0)
2024 res
= E_PROP_ID_UNSUPPORTED
;
2025 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
||
2026 dwPropID
== DSPROPERTY_EAXLISTENER_ROOM
||
2027 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMHF
||
2028 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
||
2029 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
||
2030 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
||
2031 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
||
2032 dwPropID
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
||
2033 dwPropID
== DSPROPERTY_EAXLISTENER_FLAGS
)
2035 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
|KSPROPERTY_SUPPORT_SET
;
2039 FIXME("Unhandled propid: 0x%08"LONGFMT
"x\n", dwPropID
);
2041 LeaveCriticalSection(This
->crst
);
2044 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2049 static const IKsPropertySetVtbl DS8PrimaryProp_Vtbl
=
2051 DS8PrimaryProp_QueryInterface
,
2052 DS8PrimaryProp_AddRef
,
2053 DS8PrimaryProp_Release
,
2056 DS8PrimaryProp_QuerySupport