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 void AL_APIENTRY
wrap_DeferUpdates(void)
73 { alcSuspendContext(alcGetCurrentContext()); }
74 static void AL_APIENTRY
wrap_ProcessUpdates(void)
75 { alcProcessContext(alcGetCurrentContext()); }
78 static void trigger_elapsed_notifies(DS8Buffer
*buf
, DWORD lastpos
, DWORD curpos
)
81 for(i
= 0; i
< buf
->nnotify
; ++i
)
83 DSBPOSITIONNOTIFY
*not = &buf
->notify
[i
];
84 HANDLE event
= not->hEventNotify
;
85 DWORD ofs
= not->dwOffset
;
87 if(ofs
== (DWORD
)DSBPN_OFFSETSTOP
)
93 if(ofs
< curpos
|| ofs
>= lastpos
)
99 if(ofs
>= lastpos
&& ofs
< curpos
)
104 static void trigger_stop_notifies(DS8Buffer
*buf
)
107 for(i
= 0; i
< buf
->nnotify
; ++i
)
109 DSBPOSITIONNOTIFY
*not = &buf
->notify
[i
];
110 if(not->dwOffset
== (DWORD
)DSBPN_OFFSETSTOP
)
111 SetEvent(not->hEventNotify
);
115 static DWORD CALLBACK
ThreadProc(void *dwUser
)
117 DS8Primary
*prim
= (DS8Primary
*)dwUser
;
121 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL
);
123 while(GetMessageA(&msg
, NULL
, 0, 0))
125 if(msg
.message
!= WM_USER
)
128 EnterCriticalSection(prim
->crst
);
129 setALContext(prim
->ctx
);
131 /* OpenAL doesn't support our lovely buffer extensions
132 * so just make sure enough buffers are queued
134 if(!prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
] &&
135 !prim
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] &&
136 !prim
->SupportedExt
[EXT_STATIC_BUFFER
])
138 for(i
= 0;i
< prim
->nbuffers
;++i
)
140 DS8Buffer
*buf
= prim
->buffers
[i
];
141 ALint done
= 0, queued
= QBUFFERS
, state
= AL_PLAYING
;
144 if(buf
->buffer
->numsegs
== 1 || !buf
->isplaying
)
147 alGetSourcei(buf
->source
, AL_SOURCE_STATE
, &state
);
148 alGetSourcei(buf
->source
, AL_BUFFERS_QUEUED
, &queued
);
149 alGetSourcei(buf
->source
, AL_BUFFERS_PROCESSED
, &done
);
153 alSourceUnqueueBuffers(buf
->source
, 1, &which
);
154 while(queued
< QBUFFERS
)
156 which
= buf
->buffer
->buffers
[buf
->curidx
];
157 ofs
= buf
->curidx
*buf
->buffer
->segsize
;
158 if(buf
->curidx
< buf
->buffer
->numsegs
-1)
159 alBufferData(which
, buf
->buffer
->buf_format
,
160 buf
->buffer
->data
+ ofs
, buf
->buffer
->segsize
,
161 buf
->buffer
->format
.Format
.nSamplesPerSec
);
163 alBufferData(which
, buf
->buffer
->buf_format
,
164 buf
->buffer
->data
+ ofs
, buf
->buffer
->lastsegsize
,
165 buf
->buffer
->format
.Format
.nSamplesPerSec
);
167 alSourceQueueBuffers(buf
->source
, 1, &which
);
168 buf
->curidx
= (buf
->curidx
+1)%buf
->buffer
->numsegs
;
171 if(!buf
->curidx
&& !buf
->islooping
)
173 buf
->isplaying
= FALSE
;
177 if(state
!= AL_PLAYING
)
181 IDirectSoundBuffer8_Stop(&buf
->IDirectSoundBuffer8_iface
);
184 alSourcePlay(buf
->source
);
190 for(i
= 0;i
< prim
->nnotifies
;)
192 DS8Buffer
*buf
= prim
->notifies
[i
];
193 IDirectSoundBuffer8
*dsb
= &buf
->IDirectSoundBuffer8_iface
;
194 DWORD status
=0, curpos
=buf
->lastpos
;
196 IDirectSoundBuffer8_GetStatus(dsb
, &status
);
197 IDirectSoundBuffer8_GetCurrentPosition(dsb
, &curpos
, NULL
);
198 if(buf
->lastpos
!= curpos
)
200 trigger_elapsed_notifies(buf
, buf
->lastpos
, curpos
);
201 buf
->lastpos
= curpos
;
203 if(!(status
&DSBSTATUS_PLAYING
))
205 /* Remove this buffer from list and put another at the
206 * current position; don't increment i
208 trigger_stop_notifies(buf
);
209 prim
->notifies
[i
] = prim
->notifies
[--prim
->nnotifies
];
215 LeaveCriticalSection(prim
->crst
);
221 HRESULT
DS8Primary_PreInit(DS8Primary
*This
, DS8Impl
*parent
)
223 DS3DLISTENER
*listener
;
227 This
->IDirectSoundBuffer_iface
.lpVtbl
= (IDirectSoundBufferVtbl
*)&DS8Primary_Vtbl
;
228 This
->IDirectSound3DListener_iface
.lpVtbl
= (IDirectSound3DListenerVtbl
*)&DS8Primary3D_Vtbl
;
229 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8PrimaryProp_Vtbl
;
231 This
->parent
= parent
;
232 This
->crst
= &parent
->share
->crst
;
233 This
->ctx
= parent
->share
->ctx
;
234 This
->SupportedExt
= parent
->share
->SupportedExt
;
235 This
->ExtAL
= &parent
->share
->ExtAL
;
236 This
->sources
= parent
->share
->sources
;
237 This
->auxslot
= parent
->share
->auxslot
;
239 /* Allocate enough for a WAVEFORMATEXTENSIBLE */
240 wfx
= &This
->format
.Format
;
242 wfx
->wFormatTag
= WAVE_FORMAT_PCM
;
244 wfx
->wBitsPerSample
= 8;
245 wfx
->nSamplesPerSec
= 22050;
246 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
247 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
250 This
->stopped
= TRUE
;
252 /* Apparently primary buffer size is always 32k,
253 * tested on windows with 192k 24 bits sound @ 6 channels
254 * where it will run out in 60 ms and it isn't pointer aligned
256 This
->buf_size
= 32768;
258 if(This
->SupportedExt
[SOFT_DEFERRED_UPDATES
])
260 This
->DeferUpdates
= This
->ExtAL
->DeferUpdatesSOFT
;
261 This
->ProcessUpdates
= This
->ExtAL
->ProcessUpdatesSOFT
;
265 This
->DeferUpdates
= wrap_DeferUpdates
;
266 This
->ProcessUpdates
= wrap_ProcessUpdates
;
269 This
->eax_prop
= EnvironmentDefaults
[EAX_ENVIRONMENT_GENERIC
];
270 if(This
->SupportedExt
[EXT_EFX
] && This
->auxslot
!= 0)
272 ALint revid
= alGetEnumValue("AL_EFFECT_REVERB");
273 if(revid
!= 0 && revid
!= -1)
275 This
->ExtAL
->GenEffects(1, &This
->effect
);
276 This
->ExtAL
->Effecti(This
->effect
, AL_EFFECT_TYPE
, AL_EFFECT_REVERB
);
281 /* Make sure DS3DListener defaults are applied to OpenAL */
282 listener
= &This
->listen
;
283 listener
->dwSize
= sizeof(*listener
);
284 listener
->vPosition
.x
= 0.0;
285 listener
->vPosition
.y
= 0.0;
286 listener
->vPosition
.z
= 0.0;
287 listener
->vVelocity
.x
= 0.0;
288 listener
->vVelocity
.y
= 0.0;
289 listener
->vVelocity
.z
= 0.0;
290 listener
->vOrientFront
.x
= 0.0;
291 listener
->vOrientFront
.y
= 0.0;
292 listener
->vOrientFront
.z
= 1.0;
293 listener
->vOrientTop
.x
= 0.0;
294 listener
->vOrientTop
.y
= 1.0;
295 listener
->vOrientTop
.z
= 0.0;
296 listener
->flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
297 listener
->flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
298 listener
->flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
299 hr
= IDirectSound3DListener_SetAllParameters(&This
->IDirectSound3DListener_iface
, listener
, DS3D_IMMEDIATE
);
301 ERR("Could not set 3d parameters: %08"LONGFMT
"x\n", hr
);
303 This
->sizenotifies
= This
->sizebuffers
= parent
->share
->max_sources
;
305 hr
= DSERR_OUTOFMEMORY
;
306 This
->buffers
= HeapAlloc(GetProcessHeap(), 0, This
->sizebuffers
*sizeof(*This
->buffers
));
307 This
->notifies
= HeapAlloc(GetProcessHeap(), 0, This
->sizenotifies
*sizeof(*This
->notifies
));
308 if(!This
->buffers
|| !This
->notifies
)
311 This
->thread_hdl
= CreateThread(NULL
, 0, ThreadProc
, This
, 0, &This
->thread_id
);
312 if(This
->thread_hdl
== NULL
)
318 DS8Primary_Clear(This
);
322 void DS8Primary_Clear(DS8Primary
*This
)
324 TRACE("Clearing primary %p\n", This
);
331 timeKillEvent(This
->timer_id
);
332 timeEndPeriod(This
->timer_res
);
333 TRACE("Killed timer\n");
337 PostThreadMessageA(This
->thread_id
, WM_QUIT
, 0, 0);
338 if(WaitForSingleObject(This
->thread_hdl
, 1000) != WAIT_OBJECT_0
)
339 ERR("Thread wait timed out");
340 CloseHandle(This
->thread_hdl
);
343 setALContext(This
->ctx
);
345 This
->ExtAL
->DeleteEffects(1, &This
->effect
);
347 while(This
->nbuffers
--)
348 DS8Buffer_Destroy(This
->buffers
[This
->nbuffers
]);
350 HeapFree(GetProcessHeap(), 0, This
->notifies
);
351 HeapFree(GetProcessHeap(), 0, This
->buffers
);
352 memset(This
, 0, sizeof(*This
));
355 static inline DS8Primary
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
357 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSoundBuffer_iface
);
360 static HRESULT WINAPI
DS8Primary_QueryInterface(IDirectSoundBuffer
*iface
, REFIID riid
, LPVOID
*ppv
)
362 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
364 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
367 if(IsEqualIID(riid
, &IID_IUnknown
) ||
368 IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
369 *ppv
= &This
->IDirectSoundBuffer_iface
;
370 else if(IsEqualIID(riid
, &IID_IDirectSound3DListener
))
372 if((This
->flags
&DSBCAPS_CTRL3D
))
373 *ppv
= &This
->IDirectSound3DListener_iface
;
376 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
380 IUnknown_AddRef((IUnknown
*)*ppv
);
384 return E_NOINTERFACE
;
387 static ULONG WINAPI
DS8Primary_AddRef(IDirectSoundBuffer
*iface
)
389 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
392 ret
= InterlockedIncrement(&This
->ref
);
393 if(ret
== 1) This
->flags
= 0;
398 static ULONG WINAPI
DS8Primary_Release(IDirectSoundBuffer
*iface
)
400 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
403 ret
= InterlockedDecrement(&This
->ref
);
408 static HRESULT WINAPI
DS8Primary_GetCaps(IDirectSoundBuffer
*iface
, DSBCAPS
*caps
)
410 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
412 TRACE("(%p)->(%p)\n", iface
, caps
);
414 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
416 WARN("Invalid DSBCAPS (%p, %"LONGFMT
"u)\n", caps
, caps
? caps
->dwSize
: 0);
417 return DSERR_INVALIDPARAM
;
420 EnterCriticalSection(This
->crst
);
421 caps
->dwFlags
= This
->flags
;
422 caps
->dwBufferBytes
= This
->buf_size
;
423 caps
->dwUnlockTransferRate
= 0;
424 caps
->dwPlayCpuOverhead
= 0;
425 LeaveCriticalSection(This
->crst
);
430 static HRESULT WINAPI
DS8Primary_GetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD
*playpos
, DWORD
*curpos
)
432 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
433 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
435 EnterCriticalSection(This
->crst
);
437 hr
= IDirectSoundBuffer8_GetCurrentPosition(This
->write_emu
, playpos
, curpos
);
438 LeaveCriticalSection(This
->crst
);
443 static HRESULT WINAPI
DS8Primary_GetFormat(IDirectSoundBuffer
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
445 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
451 WARN("Cannot report format or format size\n");
452 return DSERR_INVALIDPARAM
;
455 EnterCriticalSection(This
->crst
);
456 size
= sizeof(This
->format
.Format
) + This
->format
.Format
.cbSize
;
462 hr
= DSERR_INVALIDPARAM
;
464 memcpy(wfx
, &This
->format
.Format
, size
);
466 LeaveCriticalSection(This
->crst
);
471 static HRESULT WINAPI
DS8Primary_GetVolume(IDirectSoundBuffer
*iface
, LONG
*volume
)
473 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
476 TRACE("(%p)->(%p)\n", iface
, volume
);
479 return DSERR_INVALIDPARAM
;
481 EnterCriticalSection(This
->crst
);
482 if(!(This
->flags
& DSBCAPS_CTRLVOLUME
))
483 hr
= DSERR_CONTROLUNAVAIL
;
488 setALContext(This
->ctx
);
489 alGetListenerf(AL_GAIN
, &gain
);
493 *volume
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
495 LeaveCriticalSection(This
->crst
);
500 static HRESULT WINAPI
DS8Primary_GetPan(IDirectSoundBuffer
*iface
, LONG
*pan
)
502 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
505 WARN("(%p)->(%p): semi-stub\n", iface
, pan
);
508 return DSERR_INVALIDPARAM
;
510 EnterCriticalSection(This
->crst
);
512 hr
= IDirectSoundBuffer8_GetPan(This
->write_emu
, pan
);
513 else if(!(This
->flags
& DSBCAPS_CTRLPAN
))
514 hr
= DSERR_CONTROLUNAVAIL
;
517 LeaveCriticalSection(This
->crst
);
522 static HRESULT WINAPI
DS8Primary_GetFrequency(IDirectSoundBuffer
*iface
, DWORD
*freq
)
524 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
527 WARN("(%p)->(%p): semi-stub\n", iface
, freq
);
530 return DSERR_INVALIDPARAM
;
532 EnterCriticalSection(This
->crst
);
533 if(!(This
->flags
& DSBCAPS_CTRLFREQUENCY
))
534 hr
= DSERR_CONTROLUNAVAIL
;
536 *freq
= This
->format
.Format
.nSamplesPerSec
;
537 LeaveCriticalSection(This
->crst
);
542 static HRESULT WINAPI
DS8Primary_GetStatus(IDirectSoundBuffer
*iface
, DWORD
*status
)
544 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
546 TRACE("(%p)->(%p)\n", iface
, status
);
549 return DSERR_INVALIDPARAM
;
551 EnterCriticalSection(This
->crst
);
553 *status
= DSBSTATUS_PLAYING
|DSBSTATUS_LOOPING
;
554 if((This
->flags
&DSBCAPS_LOCDEFER
))
555 *status
|= DSBSTATUS_LOCHARDWARE
;
562 for(i
= 0;i
< This
->nbuffers
;++i
)
564 hr
= IDirectSoundBuffer8_GetStatus(&This
->buffers
[i
]->IDirectSoundBuffer8_iface
, &state
);
565 if(SUCCEEDED(hr
) && (state
&DSBSTATUS_PLAYING
))
568 if(i
== This
->nbuffers
)
570 /* Primary stopped and no buffers playing.. */
575 LeaveCriticalSection(This
->crst
);
580 static HRESULT WINAPI
DS8Primary_Initialize(IDirectSoundBuffer
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
582 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
585 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
587 if(!desc
|| desc
->lpwfxFormat
|| desc
->dwBufferBytes
)
589 WARN("Bad DSBDESC for primary buffer\n");
590 return DSERR_INVALIDPARAM
;
592 if((desc
->dwFlags
&DSBCAPS_CTRLFX
) ||
593 (desc
->dwFlags
&DSBCAPS_CTRLPOSITIONNOTIFY
) ||
594 (desc
->dwFlags
&DSBCAPS_LOCSOFTWARE
))
596 WARN("Bad dwFlags %08"LONGFMT
"x\n", desc
->dwFlags
);
597 return DSERR_INVALIDPARAM
;
600 EnterCriticalSection(This
->crst
);
601 /* Should be 0 if not initialized */
604 hr
= DSERR_ALREADYINITIALIZED
;
608 if(This
->parent
->prio_level
== DSSCL_WRITEPRIMARY
)
610 DSBUFFERDESC emudesc
;
615 ERR("There shouldn't be a write_emu!\n");
616 IDirectSoundBuffer8_Release(This
->write_emu
);
617 This
->write_emu
= NULL
;
620 memset(&emudesc
, 0, sizeof(emudesc
));
621 emudesc
.dwSize
= sizeof(emudesc
);
622 emudesc
.dwFlags
= DSBCAPS_LOCHARDWARE
| (desc
->dwFlags
&DSBCAPS_CTRLPAN
);
623 /* Dont play last incomplete sample */
624 emudesc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
%This
->format
.Format
.nBlockAlign
);
625 emudesc
.lpwfxFormat
= &This
->format
.Format
;
627 hr
= DS8Buffer_Create(&emu
, This
, NULL
);
630 This
->write_emu
= &emu
->IDirectSoundBuffer8_iface
;
631 hr
= IDirectSoundBuffer8_Initialize(This
->write_emu
, ds
, &emudesc
);
634 IDirectSoundBuffer8_Release(This
->write_emu
);
635 This
->write_emu
= NULL
;
641 This
->flags
= desc
->dwFlags
| DSBCAPS_LOCHARDWARE
;
643 LeaveCriticalSection(This
->crst
);
647 static HRESULT WINAPI
DS8Primary_Lock(IDirectSoundBuffer
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
649 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
650 HRESULT hr
= DSERR_PRIOLEVELNEEDED
;
652 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %p, %p, %p, %p, %"LONGFMT
"u)\n", iface
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
654 EnterCriticalSection(This
->crst
);
656 hr
= IDirectSoundBuffer8_Lock(This
->write_emu
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
657 LeaveCriticalSection(This
->crst
);
662 static HRESULT WINAPI
DS8Primary_Play(IDirectSoundBuffer
*iface
, DWORD res1
, DWORD res2
, DWORD flags
)
664 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
667 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %"LONGFMT
"u)\n", iface
, res1
, res2
, flags
);
669 if(!(flags
& DSBPLAY_LOOPING
))
671 WARN("Flags (%08"LONGFMT
"x) not set to DSBPLAY_LOOPING\n", flags
);
672 return DSERR_INVALIDPARAM
;
675 EnterCriticalSection(This
->crst
);
678 hr
= IDirectSoundBuffer8_Play(This
->write_emu
, res1
, res2
, flags
);
680 This
->stopped
= FALSE
;
681 LeaveCriticalSection(This
->crst
);
686 static HRESULT WINAPI
DS8Primary_SetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD pos
)
688 WARN("(%p)->(%"LONGFMT
"u)\n", iface
, pos
);
689 return DSERR_INVALIDCALL
;
692 /* Just assume the format is crap, and clean up the damage */
693 static void copy_waveformat(WAVEFORMATEX
*wfx
, const WAVEFORMATEX
*from
)
695 if(from
->wFormatTag
== WAVE_FORMAT_PCM
)
698 if(from
->wBitsPerSample
== 8 ||
699 from
->wBitsPerSample
== 16 ||
700 from
->wBitsPerSample
== 24 ||
701 from
->wBitsPerSample
== 32)
702 wfx
->wBitsPerSample
= from
->wBitsPerSample
;
704 else if(from
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
706 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)wfx
;
707 const WAVEFORMATEXTENSIBLE
*fromx
= (const WAVEFORMATEXTENSIBLE
*)from
;
708 DWORD size
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
710 /* Fail silently.. */
711 if(from
->cbSize
< size
)
713 if(!fromx
->Samples
.wValidBitsPerSample
&&
714 !fromx
->Format
.wBitsPerSample
)
717 if(!IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
718 !IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
720 ERR("Unhandled extensible format: %s\n", debugstr_guid(&wfe
->SubFormat
));
724 wfe
->Format
.wBitsPerSample
= from
->wBitsPerSample
;
725 wfe
->Samples
.wValidBitsPerSample
= fromx
->Samples
.wValidBitsPerSample
;
726 if(!wfe
->Samples
.wValidBitsPerSample
)
727 wfe
->Samples
.wValidBitsPerSample
= wfe
->Format
.wBitsPerSample
;
728 wfe
->Format
.cbSize
= size
;
729 wfe
->dwChannelMask
= fromx
->dwChannelMask
;
730 wfe
->SubFormat
= fromx
->SubFormat
;
734 ERR("Unhandled format tag %04x\n", from
->wFormatTag
);
739 wfx
->nChannels
= from
->nChannels
;
740 wfx
->wFormatTag
= from
->wFormatTag
;
741 if(from
->nSamplesPerSec
>= DSBFREQUENCY_MIN
&&
742 from
->nSamplesPerSec
<= DSBFREQUENCY_MAX
)
743 wfx
->nSamplesPerSec
= from
->nSamplesPerSec
;
744 wfx
->nBlockAlign
= wfx
->wBitsPerSample
* wfx
->nChannels
/ 8;
745 wfx
->nAvgBytesPerSec
= wfx
->nSamplesPerSec
* wfx
->nBlockAlign
;
748 static HRESULT WINAPI
DS8Primary_SetFormat(IDirectSoundBuffer
*iface
, const WAVEFORMATEX
*wfx
)
750 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
754 TRACE("(%p)->(%p)\n", iface
, wfx
);
758 WARN("Missing format\n");
759 return DSERR_INVALIDPARAM
;
762 EnterCriticalSection(This
->crst
);
764 if(This
->parent
->prio_level
< DSSCL_PRIORITY
)
766 hr
= DSERR_PRIOLEVELNEEDED
;
770 TRACE("Requested primary format:\n"
771 " FormatTag = %04x\n"
773 " SamplesPerSec = %"LONGFMT
"u\n"
774 " AvgBytesPerSec = %"LONGFMT
"u\n"
776 " BitsPerSample = %u\n",
777 wfx
->wFormatTag
, wfx
->nChannels
,
778 wfx
->nSamplesPerSec
, wfx
->nAvgBytesPerSec
,
779 wfx
->nBlockAlign
, wfx
->wBitsPerSample
);
781 copy_waveformat(&This
->format
.Format
, wfx
);
783 freq
= This
->format
.Format
.nSamplesPerSec
;
784 alcGetIntegerv(This
->parent
->device
, ALC_FREQUENCY
, 1, &freq
);
785 checkALCError(This
->parent
->device
);
787 This
->format
.Format
.nSamplesPerSec
= freq
;
788 This
->format
.Format
.nAvgBytesPerSec
= This
->format
.Format
.nBlockAlign
*
789 This
->format
.Format
.nSamplesPerSec
;
796 memset(&desc
, 0, sizeof(desc
));
797 desc
.dwSize
= sizeof(desc
);
798 desc
.dwFlags
= DSBCAPS_LOCHARDWARE
|DSBCAPS_CTRLPAN
;
799 desc
.dwBufferBytes
= This
->buf_size
- (This
->buf_size
% This
->format
.Format
.nBlockAlign
);
800 desc
.lpwfxFormat
= &This
->format
.Format
;
802 hr
= DS8Buffer_Create(&buf
, This
, NULL
);
806 hr
= IDirectSoundBuffer8_Initialize(&buf
->IDirectSoundBuffer8_iface
, &This
->parent
->IDirectSound_iface
, &desc
);
808 DS8Buffer_Destroy(buf
);
811 IDirectSoundBuffer8_Release(This
->write_emu
);
812 This
->write_emu
= &buf
->IDirectSoundBuffer8_iface
;
817 LeaveCriticalSection(This
->crst
);
821 static HRESULT WINAPI
DS8Primary_SetVolume(IDirectSoundBuffer
*iface
, LONG vol
)
823 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
826 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, vol
);
828 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
830 WARN("Invalid volume (%"LONGFMT
"d)\n", vol
);
831 return DSERR_INVALIDPARAM
;
834 EnterCriticalSection(This
->crst
);
835 if(!(This
->flags
&DSBCAPS_CTRLVOLUME
))
836 hr
= DSERR_CONTROLUNAVAIL
;
839 setALContext(This
->ctx
);
840 alListenerf(AL_GAIN
, mB_to_gain(vol
));
843 LeaveCriticalSection(This
->crst
);
848 static HRESULT WINAPI
DS8Primary_SetPan(IDirectSoundBuffer
*iface
, LONG pan
)
850 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
853 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, pan
);
855 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
857 WARN("invalid parameter: pan = %"LONGFMT
"d\n", pan
);
858 return DSERR_INVALIDPARAM
;
861 EnterCriticalSection(This
->crst
);
862 if(!(This
->flags
&DSBCAPS_CTRLPAN
))
864 WARN("control unavailable\n");
865 hr
= DSERR_CONTROLUNAVAIL
;
867 else if(This
->write_emu
)
868 hr
= IDirectSoundBuffer8_SetPan(This
->write_emu
, pan
);
871 FIXME("Not supported\n");
874 LeaveCriticalSection(This
->crst
);
879 static HRESULT WINAPI
DS8Primary_SetFrequency(IDirectSoundBuffer
*iface
, DWORD freq
)
881 WARN("(%p)->(%"LONGFMT
"u)\n", iface
, freq
);
882 return DSERR_CONTROLUNAVAIL
;
885 static HRESULT WINAPI
DS8Primary_Stop(IDirectSoundBuffer
*iface
)
887 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
890 TRACE("(%p)->()\n", iface
);
892 EnterCriticalSection(This
->crst
);
894 hr
= IDirectSoundBuffer8_Stop(This
->write_emu
);
896 This
->stopped
= TRUE
;
897 LeaveCriticalSection(This
->crst
);
902 static HRESULT WINAPI
DS8Primary_Unlock(IDirectSoundBuffer
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
904 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
905 HRESULT hr
= DSERR_INVALIDCALL
;
907 TRACE("(%p)->(%p, %"LONGFMT
"u, %p, %"LONGFMT
"u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
909 EnterCriticalSection(This
->crst
);
911 hr
= IDirectSoundBuffer8_Unlock(This
->write_emu
, ptr1
, len1
, ptr2
, len2
);
912 LeaveCriticalSection(This
->crst
);
917 static HRESULT WINAPI
DS8Primary_Restore(IDirectSoundBuffer
*iface
)
919 DS8Primary
*This
= impl_from_IDirectSoundBuffer(iface
);
922 TRACE("(%p)->()\n", iface
);
924 EnterCriticalSection(This
->crst
);
926 hr
= IDirectSoundBuffer8_Restore(This
->write_emu
);
927 LeaveCriticalSection(This
->crst
);
932 static const IDirectSoundBufferVtbl DS8Primary_Vtbl
=
934 DS8Primary_QueryInterface
,
938 DS8Primary_GetCurrentPosition
,
939 DS8Primary_GetFormat
,
940 DS8Primary_GetVolume
,
942 DS8Primary_GetFrequency
,
943 DS8Primary_GetStatus
,
944 DS8Primary_Initialize
,
947 DS8Primary_SetCurrentPosition
,
948 DS8Primary_SetFormat
,
949 DS8Primary_SetVolume
,
951 DS8Primary_SetFrequency
,
957 static inline DS8Primary
*impl_from_IDirectSound3DListener(IDirectSound3DListener
*iface
)
959 return CONTAINING_RECORD(iface
, DS8Primary
, IDirectSound3DListener_iface
);
962 static HRESULT WINAPI
DS8Primary3D_QueryInterface(IDirectSound3DListener
*iface
, REFIID riid
, void **ppv
)
964 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
965 return DS8Primary_QueryInterface(&This
->IDirectSoundBuffer_iface
, riid
, ppv
);
968 static ULONG WINAPI
DS8Primary3D_AddRef(IDirectSound3DListener
*iface
)
970 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
973 ret
= InterlockedIncrement(&This
->ds3d_ref
);
974 TRACE("new refcount %"LONGFMT
"d\n", ret
);
980 /* Considering the primary buffer doesn't get destroyed
981 * it doesn't make sense to destroy ds3d here
983 static ULONG WINAPI
DS8Primary3D_Release(IDirectSound3DListener
*iface
)
985 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
988 ret
= InterlockedDecrement(&This
->ds3d_ref
);
989 TRACE("new refcount %"LONGFMT
"d\n", ret
);
995 static HRESULT WINAPI
DS8Primary3D_GetAllParameters(IDirectSound3DListener
*iface
, DS3DLISTENER
*listener
)
997 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
999 TRACE("(%p)->(%p)\n", iface
, listener
);
1001 if(!listener
|| listener
->dwSize
< sizeof(*listener
))
1003 WARN("Invalid DS3DLISTENER %p %"LONGFMT
"u\n", listener
, listener
? listener
->dwSize
: 0);
1004 return DSERR_INVALIDPARAM
;
1007 EnterCriticalSection(This
->crst
);
1008 setALContext(This
->ctx
);
1009 IDirectSound3DListener_GetPosition(iface
, &listener
->vPosition
);
1010 IDirectSound3DListener_GetVelocity(iface
, &listener
->vVelocity
);
1011 IDirectSound3DListener_GetOrientation(iface
, &listener
->vOrientFront
, &listener
->vOrientTop
);
1012 IDirectSound3DListener_GetDistanceFactor(iface
, &listener
->flDistanceFactor
);
1013 IDirectSound3DListener_GetRolloffFactor(iface
, &listener
->flRolloffFactor
);
1014 IDirectSound3DListener_GetRolloffFactor(iface
, &listener
->flDopplerFactor
);
1016 LeaveCriticalSection(This
->crst
);
1021 static HRESULT WINAPI
DS8Primary3D_GetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE
*distancefactor
)
1023 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1025 TRACE("(%p)->(%p)\n", iface
, distancefactor
);
1029 WARN("Invalid parameter %p\n", distancefactor
);
1030 return DSERR_INVALIDPARAM
;
1033 EnterCriticalSection(This
->crst
);
1034 setALContext(This
->ctx
);
1036 *distancefactor
= 343.3f
/alGetFloat(AL_SPEED_OF_SOUND
);
1040 LeaveCriticalSection(This
->crst
);
1045 static HRESULT WINAPI
DS8Primary3D_GetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE
*dopplerfactor
)
1047 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1049 TRACE("(%p)->(%p)\n", iface
, dopplerfactor
);
1053 WARN("Invalid parameter %p\n", dopplerfactor
);
1054 return DSERR_INVALIDPARAM
;
1057 EnterCriticalSection(This
->crst
);
1058 setALContext(This
->ctx
);
1060 *dopplerfactor
= alGetFloat(AL_DOPPLER_FACTOR
);
1064 LeaveCriticalSection(This
->crst
);
1069 static HRESULT WINAPI
DS8Primary3D_GetOrientation(IDirectSound3DListener
*iface
, D3DVECTOR
*front
, D3DVECTOR
*top
)
1071 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1074 TRACE("(%p)->(%p, %p)\n", iface
, front
, top
);
1078 WARN("Invalid parameter %p %p\n", front
, top
);
1079 return DSERR_INVALIDPARAM
;
1082 EnterCriticalSection(This
->crst
);
1083 setALContext(This
->ctx
);
1085 alGetListenerfv(AL_ORIENTATION
, orient
);
1088 front
->x
= orient
[0];
1089 front
->y
= orient
[1];
1090 front
->z
= -orient
[2];
1093 top
->z
= -orient
[5];
1096 LeaveCriticalSection(This
->crst
);
1101 static HRESULT WINAPI
DS8Primary3D_GetPosition(IDirectSound3DListener
*iface
, D3DVECTOR
*pos
)
1103 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1106 TRACE("(%p)->(%p)\n", iface
, pos
);
1110 WARN("Invalid parameter %p\n", pos
);
1111 return DSERR_INVALIDPARAM
;
1114 EnterCriticalSection(This
->crst
);
1115 setALContext(This
->ctx
);
1117 alGetListenerfv(AL_POSITION
, alpos
);
1125 LeaveCriticalSection(This
->crst
);
1130 static HRESULT WINAPI
DS8Primary3D_GetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE
*rollofffactor
)
1132 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1134 TRACE("(%p)->(%p)\n", iface
, rollofffactor
);
1138 WARN("Invalid parameter %p\n", rollofffactor
);
1139 return DSERR_INVALIDPARAM
;
1142 EnterCriticalSection(This
->crst
);
1143 *rollofffactor
= This
->rollofffactor
;
1144 LeaveCriticalSection(This
->crst
);
1149 static HRESULT WINAPI
DS8Primary3D_GetVelocity(IDirectSound3DListener
*iface
, D3DVECTOR
*velocity
)
1151 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1154 TRACE("(%p)->(%p)\n", iface
, velocity
);
1158 WARN("Invalid parameter %p\n", velocity
);
1159 return DSERR_INVALIDPARAM
;
1162 EnterCriticalSection(This
->crst
);
1163 setALContext(This
->ctx
);
1165 alGetListenerfv(AL_VELOCITY
, vel
);
1168 velocity
->x
= vel
[0];
1169 velocity
->y
= vel
[1];
1170 velocity
->z
= -vel
[2];
1173 LeaveCriticalSection(This
->crst
);
1178 static HRESULT WINAPI
DS8Primary3D_SetAllParameters(IDirectSound3DListener
*iface
, const DS3DLISTENER
*listen
, DWORD apply
)
1180 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1182 TRACE("(%p)->(%p, %"LONGFMT
"u)\n", iface
, listen
, apply
);
1184 if(!listen
|| listen
->dwSize
< sizeof(*listen
))
1186 WARN("Invalid parameter %p %"LONGFMT
"u\n", listen
, listen
? listen
->dwSize
: 0);
1187 return DSERR_INVALIDPARAM
;
1190 if(listen
->flDistanceFactor
> DS3D_MAXDISTANCEFACTOR
||
1191 listen
->flDistanceFactor
< DS3D_MINDISTANCEFACTOR
)
1193 WARN("Invalid distance factor (%f)\n", listen
->flDistanceFactor
);
1194 return DSERR_INVALIDPARAM
;
1197 if(listen
->flDopplerFactor
> DS3D_MAXDOPPLERFACTOR
||
1198 listen
->flDopplerFactor
< DS3D_MINDOPPLERFACTOR
)
1200 WARN("Invalid doppler factor (%f)\n", listen
->flDopplerFactor
);
1201 return DSERR_INVALIDPARAM
;
1204 if(listen
->flRolloffFactor
< DS3D_MINROLLOFFFACTOR
||
1205 listen
->flRolloffFactor
> DS3D_MAXROLLOFFFACTOR
)
1207 WARN("Invalid rolloff factor (%f)\n", listen
->flRolloffFactor
);
1208 return DSERR_INVALIDPARAM
;
1211 EnterCriticalSection(This
->crst
);
1212 setALContext(This
->ctx
);
1213 IDirectSound3DListener_SetPosition(iface
, listen
->vPosition
.x
, listen
->vPosition
.y
, listen
->vPosition
.z
, apply
);
1214 IDirectSound3DListener_SetVelocity(iface
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, listen
->vVelocity
.z
, apply
);
1215 IDirectSound3DListener_SetOrientation(iface
, listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, listen
->vOrientFront
.z
,
1216 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, listen
->vOrientTop
.z
, apply
);
1217 IDirectSound3DListener_SetDistanceFactor(iface
, listen
->flDistanceFactor
, apply
);
1218 IDirectSound3DListener_SetRolloffFactor(iface
, listen
->flRolloffFactor
, apply
);
1219 IDirectSound3DListener_SetDopplerFactor(iface
, listen
->flDopplerFactor
, apply
);
1221 LeaveCriticalSection(This
->crst
);
1226 static HRESULT WINAPI
DS8Primary3D_SetDistanceFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1228 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1230 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", iface
, factor
, apply
);
1232 if(factor
< DS3D_MINDISTANCEFACTOR
||
1233 factor
> DS3D_MAXDISTANCEFACTOR
)
1235 WARN("Invalid parameter %f\n", factor
);
1236 return DSERR_INVALIDPARAM
;
1239 EnterCriticalSection(This
->crst
);
1240 if(apply
== DS3D_DEFERRED
)
1242 This
->listen
.flDistanceFactor
= factor
;
1243 This
->dirty
.bit
.distancefactor
= 1;
1247 setALContext(This
->ctx
);
1248 alSpeedOfSound(343.3f
/factor
);
1249 if(This
->SupportedExt
[EXT_EFX
])
1250 alListenerf(AL_METERS_PER_UNIT
, factor
);
1254 LeaveCriticalSection(This
->crst
);
1259 static HRESULT WINAPI
DS8Primary3D_SetDopplerFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1261 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1263 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", iface
, factor
, apply
);
1265 if(factor
< DS3D_MINDOPPLERFACTOR
||
1266 factor
> DS3D_MAXDOPPLERFACTOR
)
1268 WARN("Invalid parameter %f\n", factor
);
1269 return DSERR_INVALIDPARAM
;
1272 EnterCriticalSection(This
->crst
);
1273 if(apply
== DS3D_DEFERRED
)
1275 This
->listen
.flDopplerFactor
= factor
;
1276 This
->dirty
.bit
.dopplerfactor
= 1;
1280 setALContext(This
->ctx
);
1281 alDopplerFactor(factor
);
1285 LeaveCriticalSection(This
->crst
);
1290 static HRESULT WINAPI
DS8Primary3D_SetOrientation(IDirectSound3DListener
*iface
, D3DVALUE xFront
, D3DVALUE yFront
, D3DVALUE zFront
, D3DVALUE xTop
, D3DVALUE yTop
, D3DVALUE zTop
, DWORD apply
)
1292 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1294 TRACE("(%p)->(%f, %f, %f, %f, %f, %f, %"LONGFMT
"u)\n", iface
, xFront
, yFront
, zFront
, xTop
, yTop
, zTop
, apply
);
1296 EnterCriticalSection(This
->crst
);
1297 if(apply
== DS3D_DEFERRED
)
1299 This
->listen
.vOrientFront
.x
= xFront
;
1300 This
->listen
.vOrientFront
.y
= yFront
;
1301 This
->listen
.vOrientFront
.z
= zFront
;
1302 This
->listen
.vOrientTop
.x
= xTop
;
1303 This
->listen
.vOrientTop
.y
= yTop
;
1304 This
->listen
.vOrientTop
.z
= zTop
;
1305 This
->dirty
.bit
.orientation
= 1;
1309 ALfloat orient
[6] = {
1310 xFront
, yFront
, -zFront
,
1313 setALContext(This
->ctx
);
1314 alListenerfv(AL_ORIENTATION
, orient
);
1318 LeaveCriticalSection(This
->crst
);
1323 static HRESULT WINAPI
DS8Primary3D_SetPosition(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1325 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1327 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", iface
, x
, y
, z
, apply
);
1329 EnterCriticalSection(This
->crst
);
1330 if(apply
== DS3D_DEFERRED
)
1332 This
->listen
.vPosition
.x
= x
;
1333 This
->listen
.vPosition
.y
= y
;
1334 This
->listen
.vPosition
.z
= z
;
1335 This
->dirty
.bit
.pos
= 1;
1339 setALContext(This
->ctx
);
1340 alListener3f(AL_POSITION
, x
, y
, -z
);
1344 LeaveCriticalSection(This
->crst
);
1349 static HRESULT WINAPI
DS8Primary3D_SetRolloffFactor(IDirectSound3DListener
*iface
, D3DVALUE factor
, DWORD apply
)
1351 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1353 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", iface
, factor
, apply
);
1355 if(factor
< DS3D_MINROLLOFFFACTOR
||
1356 factor
> DS3D_MAXROLLOFFFACTOR
)
1358 WARN("Invalid parameter %f\n", factor
);
1359 return DSERR_INVALIDPARAM
;
1362 EnterCriticalSection(This
->crst
);
1363 if(apply
== DS3D_DEFERRED
)
1365 This
->listen
.flRolloffFactor
= factor
;
1366 This
->dirty
.bit
.rollofffactor
= 1;
1372 setALContext(This
->ctx
);
1373 for(i
= 0;i
< This
->nbuffers
;++i
)
1375 if(This
->buffers
[i
]->ds3dmode
!= DS3DMODE_DISABLE
)
1376 alSourcef(This
->buffers
[i
]->source
, AL_ROLLOFF_FACTOR
, factor
);
1381 This
->rollofffactor
= factor
;
1383 LeaveCriticalSection(This
->crst
);
1388 static HRESULT WINAPI
DS8Primary3D_SetVelocity(IDirectSound3DListener
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1390 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1392 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", iface
, x
, y
, z
, apply
);
1394 EnterCriticalSection(This
->crst
);
1395 if(apply
== DS3D_DEFERRED
)
1397 This
->listen
.vVelocity
.x
= x
;
1398 This
->listen
.vVelocity
.y
= y
;
1399 This
->listen
.vVelocity
.z
= z
;
1400 This
->dirty
.bit
.vel
= 1;
1404 setALContext(This
->ctx
);
1405 alListener3f(AL_VELOCITY
, x
, y
, -z
);
1409 LeaveCriticalSection(This
->crst
);
1414 static HRESULT WINAPI
DS8Primary3D_CommitDeferredSettings(IDirectSound3DListener
*iface
)
1416 DS8Primary
*This
= impl_from_IDirectSound3DListener(iface
);
1417 const DS3DLISTENER
*listen
= &This
->listen
;
1420 EnterCriticalSection(This
->crst
);
1421 setALContext(This
->ctx
);
1422 This
->DeferUpdates();
1424 if(This
->dirty
.bit
.pos
)
1425 alListener3f(AL_POSITION
, listen
->vPosition
.x
, listen
->vPosition
.y
, -listen
->vPosition
.z
);
1426 if(This
->dirty
.bit
.vel
)
1427 alListener3f(AL_VELOCITY
, listen
->vVelocity
.x
, listen
->vVelocity
.y
, -listen
->vVelocity
.z
);
1428 if(This
->dirty
.bit
.orientation
)
1430 ALfloat orient
[6] = {
1431 listen
->vOrientFront
.x
, listen
->vOrientFront
.y
, -listen
->vOrientFront
.z
,
1432 listen
->vOrientTop
.x
, listen
->vOrientTop
.y
, -listen
->vOrientTop
.z
1434 alListenerfv(AL_ORIENTATION
, orient
);
1436 if(This
->dirty
.bit
.distancefactor
)
1438 alSpeedOfSound(343.3f
/listen
->flDistanceFactor
);
1439 if(This
->SupportedExt
[EXT_EFX
])
1440 alListenerf(AL_METERS_PER_UNIT
, listen
->flDistanceFactor
);
1443 if(This
->dirty
.bit
.rollofffactor
)
1445 ALfloat rolloff
= This
->rollofffactor
;
1446 for(i
= 0;i
< This
->nbuffers
;++i
)
1448 DS8Buffer
*buf
= This
->buffers
[i
];
1449 if(buf
->ds3dmode
!= DS3DMODE_DISABLE
)
1450 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
, rolloff
);
1454 if(This
->dirty
.bit
.dopplerfactor
)
1455 alDopplerFactor(listen
->flDopplerFactor
);
1457 if(This
->dirty
.bit
.effect
)
1458 This
->ExtAL
->AuxiliaryEffectSloti(This
->auxslot
, AL_EFFECTSLOT_EFFECT
, This
->effect
);
1460 /* checkALError is here for debugging */
1463 TRACE("Dirty flags was: 0x%02x\n", This
->dirty
.flags
);
1464 This
->dirty
.flags
= 0;
1466 for(i
= 0;i
< This
->nbuffers
;++i
)
1468 DS8Buffer
*buf
= This
->buffers
[i
];
1470 if(!buf
->dirty
.flags
)
1473 if(buf
->dirty
.bit
.pos
)
1474 alSource3f(buf
->source
, AL_POSITION
,
1475 buf
->ds3dbuffer
.vPosition
.x
,
1476 buf
->ds3dbuffer
.vPosition
.y
,
1477 -buf
->ds3dbuffer
.vPosition
.z
);
1478 if(buf
->dirty
.bit
.vel
)
1479 alSource3f(buf
->source
, AL_VELOCITY
,
1480 buf
->ds3dbuffer
.vVelocity
.x
,
1481 buf
->ds3dbuffer
.vVelocity
.y
,
1482 -buf
->ds3dbuffer
.vVelocity
.z
);
1483 if(buf
->dirty
.bit
.cone_angles
)
1485 alSourcei(buf
->source
, AL_CONE_INNER_ANGLE
,
1486 buf
->ds3dbuffer
.dwInsideConeAngle
);
1487 alSourcei(buf
->source
, AL_CONE_OUTER_ANGLE
,
1488 buf
->ds3dbuffer
.dwOutsideConeAngle
);
1490 if(buf
->dirty
.bit
.cone_orient
)
1491 alSource3f(buf
->source
, AL_DIRECTION
,
1492 buf
->ds3dbuffer
.vConeOrientation
.x
,
1493 buf
->ds3dbuffer
.vConeOrientation
.y
,
1494 -buf
->ds3dbuffer
.vConeOrientation
.z
);
1495 if(buf
->dirty
.bit
.cone_outsidevolume
)
1496 alSourcef(buf
->source
, AL_CONE_OUTER_GAIN
,
1497 mB_to_gain(buf
->ds3dbuffer
.lConeOutsideVolume
));
1498 if(buf
->dirty
.bit
.min_distance
)
1499 alSourcef(buf
->source
, AL_REFERENCE_DISTANCE
, buf
->ds3dbuffer
.flMinDistance
);
1500 if(buf
->dirty
.bit
.max_distance
)
1501 alSourcef(buf
->source
, AL_MAX_DISTANCE
, buf
->ds3dbuffer
.flMaxDistance
);
1502 if(buf
->dirty
.bit
.mode
)
1504 buf
->ds3dmode
= buf
->ds3dbuffer
.dwMode
;
1505 alSourcei(buf
->source
, AL_SOURCE_RELATIVE
,
1506 (buf
->ds3dmode
!=DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
1507 alSourcef(buf
->source
, AL_ROLLOFF_FACTOR
,
1508 (buf
->ds3dmode
==DS3DMODE_DISABLE
) ? 0.0f
: This
->rollofffactor
);
1510 buf
->dirty
.flags
= 0;
1514 This
->ProcessUpdates();
1516 LeaveCriticalSection(This
->crst
);
1521 static const IDirectSound3DListenerVtbl DS8Primary3D_Vtbl
=
1523 DS8Primary3D_QueryInterface
,
1524 DS8Primary3D_AddRef
,
1525 DS8Primary3D_Release
,
1526 DS8Primary3D_GetAllParameters
,
1527 DS8Primary3D_GetDistanceFactor
,
1528 DS8Primary3D_GetDopplerFactor
,
1529 DS8Primary3D_GetOrientation
,
1530 DS8Primary3D_GetPosition
,
1531 DS8Primary3D_GetRolloffFactor
,
1532 DS8Primary3D_GetVelocity
,
1533 DS8Primary3D_SetAllParameters
,
1534 DS8Primary3D_SetDistanceFactor
,
1535 DS8Primary3D_SetDopplerFactor
,
1536 DS8Primary3D_SetOrientation
,
1537 DS8Primary3D_SetPosition
,
1538 DS8Primary3D_SetRolloffFactor
,
1539 DS8Primary3D_SetVelocity
,
1540 DS8Primary3D_CommitDeferredSettings
1543 /* NOTE: Although the app handles listener properties through secondary buffers,
1544 * we pass the requests to the primary buffer though a propertyset interface.
1545 * These methods are not exposed to the app. */
1546 static inline DS8Primary
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
1548 return CONTAINING_RECORD(iface
, DS8Primary
, IKsPropertySet_iface
);
1551 static HRESULT WINAPI
DS8PrimaryProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
1553 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1554 return DS8Primary_QueryInterface(&This
->IDirectSoundBuffer_iface
, riid
, ppv
);
1557 static ULONG WINAPI
DS8PrimaryProp_AddRef(IKsPropertySet
*iface
)
1559 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1562 ret
= InterlockedIncrement(&This
->prop_ref
);
1563 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1568 static ULONG WINAPI
DS8PrimaryProp_Release(IKsPropertySet
*iface
)
1570 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1573 ret
= InterlockedDecrement(&This
->prop_ref
);
1574 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1579 static HRESULT WINAPI
DS8PrimaryProp_Get(IKsPropertySet
*iface
,
1580 REFGUID guidPropSet
, ULONG dwPropID
,
1581 LPVOID pInstanceData
, ULONG cbInstanceData
,
1582 LPVOID pPropData
, ULONG cbPropData
,
1585 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1586 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1587 (void)pInstanceData
;
1588 (void)cbInstanceData
;
1590 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1592 EnterCriticalSection(This
->crst
);
1594 if(This
->effect
== 0)
1595 res
= E_PROP_ID_UNSUPPORTED
;
1596 else switch(dwPropID
)
1598 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
1599 res
= DSERR_INVALIDPARAM
;
1600 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1604 EAXLISTENERPROPERTIES
*props
;
1605 } data
= { pPropData
};
1607 *data
.props
= This
->eax_prop
;
1608 *pcbReturned
= sizeof(EAXLISTENERPROPERTIES
);
1613 case DSPROPERTY_EAXLISTENER_ROOM
:
1614 res
= DSERR_INVALIDPARAM
;
1615 if(cbPropData
>= sizeof(LONG
))
1620 } data
= { pPropData
};
1622 *data
.l
= This
->eax_prop
.lRoom
;
1623 *pcbReturned
= sizeof(LONG
);
1627 case DSPROPERTY_EAXLISTENER_ROOMHF
:
1628 res
= DSERR_INVALIDPARAM
;
1629 if(cbPropData
>= sizeof(LONG
))
1634 } data
= { pPropData
};
1636 *data
.l
= This
->eax_prop
.lRoomHF
;
1637 *pcbReturned
= sizeof(LONG
);
1642 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
1643 res
= DSERR_INVALIDPARAM
;
1644 if(cbPropData
>= sizeof(FLOAT
))
1649 } data
= { pPropData
};
1651 *data
.fl
= This
->eax_prop
.flRoomRolloffFactor
;
1652 *pcbReturned
= sizeof(FLOAT
);
1657 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
1658 res
= DSERR_INVALIDPARAM
;
1659 if(cbPropData
>= sizeof(DWORD
))
1664 } data
= { pPropData
};
1666 *data
.dw
= This
->eax_prop
.dwEnvironment
;
1667 *pcbReturned
= sizeof(DWORD
);
1672 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
1673 res
= DSERR_INVALIDPARAM
;
1674 if(cbPropData
>= sizeof(FLOAT
))
1679 } data
= { pPropData
};
1681 *data
.fl
= This
->eax_prop
.flEnvironmentSize
;
1682 *pcbReturned
= sizeof(FLOAT
);
1686 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
1687 res
= DSERR_INVALIDPARAM
;
1688 if(cbPropData
>= sizeof(FLOAT
))
1693 } data
= { pPropData
};
1695 *data
.fl
= This
->eax_prop
.flEnvironmentDiffusion
;
1696 *pcbReturned
= sizeof(FLOAT
);
1701 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
1702 res
= DSERR_INVALIDPARAM
;
1703 if(cbPropData
>= sizeof(FLOAT
))
1708 } data
= { pPropData
};
1710 *data
.fl
= This
->eax_prop
.flAirAbsorptionHF
;
1711 *pcbReturned
= sizeof(FLOAT
);
1716 case DSPROPERTY_EAXLISTENER_FLAGS
:
1717 res
= DSERR_INVALIDPARAM
;
1718 if(cbPropData
>= sizeof(DWORD
))
1723 } data
= { pPropData
};
1725 *data
.dw
= This
->eax_prop
.dwFlags
;
1726 *pcbReturned
= sizeof(DWORD
);
1732 FIXME("Unhandled propid: 0x%08"LONGFMT
"x\n", dwPropID
);
1736 LeaveCriticalSection(This
->crst
);
1739 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
1744 static HRESULT WINAPI
DS8PrimaryProp_Set(IKsPropertySet
*iface
,
1745 REFGUID guidPropSet
, ULONG dwPropID
,
1746 LPVOID pInstanceData
, ULONG cbInstanceData
,
1747 LPVOID pPropData
, ULONG cbPropData
)
1749 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
1750 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
1751 (void)pInstanceData
;
1752 (void)cbInstanceData
;
1754 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
1756 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXLISTENER_DEFERRED
;
1757 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXLISTENER_DEFERRED
);
1759 EnterCriticalSection(This
->crst
);
1760 setALContext(This
->ctx
);
1762 if(This
->effect
== 0)
1763 res
= E_PROP_ID_UNSUPPORTED
;
1766 case 0: /* 0 = not setting any property, just apply */
1770 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
1772 res
= DSERR_INVALIDPARAM
;
1773 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
1777 const EAXLISTENERPROPERTIES
*props
;
1778 } data
= { pPropData
};
1780 /* FIXME: Need to validate property values... Ignore? Clamp? Error? */
1781 This
->eax_prop
= *data
.props
;
1782 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DENSITY
,
1783 (data
.props
->flEnvironmentSize
< 2.0f
) ?
1784 (data
.props
->flEnvironmentSize
- 1.0f
) : 1.0f
);
1785 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
1786 data
.props
->flEnvironmentDiffusion
);
1788 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAIN
,
1789 mB_to_gain(data
.props
->lRoom
));
1790 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAINHF
,
1791 mB_to_gain(data
.props
->lRoomHF
));
1793 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1794 data
.props
->flRoomRolloffFactor
);
1796 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DECAY_TIME
,
1797 data
.props
->flDecayTime
);
1798 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DECAY_HFRATIO
,
1799 data
.props
->flDecayHFRatio
);
1801 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_REFLECTIONS_GAIN
,
1802 mB_to_gain(data
.props
->lReflections
));
1803 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_REFLECTIONS_DELAY
,
1804 data
.props
->flReflectionsDelay
);
1806 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_LATE_REVERB_GAIN
,
1807 mB_to_gain(data
.props
->lReverb
));
1808 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_LATE_REVERB_DELAY
,
1809 data
.props
->flReverbDelay
);
1811 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
1812 mB_to_gain(data
.props
->flAirAbsorptionHF
));
1814 This
->ExtAL
->Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
1815 (data
.props
->dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
1816 AL_TRUE
: AL_FALSE
);
1820 This
->dirty
.bit
.effect
= 1;
1825 case DSPROPERTY_EAXLISTENER_ROOM
:
1826 res
= DSERR_INVALIDPARAM
;
1827 if(cbPropData
>= sizeof(LONG
))
1832 } data
= { pPropData
};
1834 This
->eax_prop
.lRoom
= *data
.l
;
1835 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAIN
,
1836 mB_to_gain(This
->eax_prop
.lRoom
));
1839 This
->dirty
.bit
.effect
= 1;
1843 case DSPROPERTY_EAXLISTENER_ROOMHF
:
1844 res
= DSERR_INVALIDPARAM
;
1845 if(cbPropData
>= sizeof(LONG
))
1850 } data
= { pPropData
};
1852 This
->eax_prop
.lRoomHF
= *data
.l
;
1853 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_GAINHF
,
1854 mB_to_gain(This
->eax_prop
.lRoomHF
));
1857 This
->dirty
.bit
.effect
= 1;
1862 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
1863 res
= DSERR_INVALIDPARAM
;
1864 if(cbPropData
>= sizeof(FLOAT
))
1869 } data
= { pPropData
};
1871 This
->eax_prop
.flRoomRolloffFactor
= *data
.fl
;
1872 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
1873 This
->eax_prop
.flRoomRolloffFactor
);
1876 This
->dirty
.bit
.effect
= 1;
1881 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
1882 res
= DSERR_INVALIDPARAM
;
1883 if(cbPropData
>= sizeof(DWORD
))
1888 } data
= { pPropData
};
1890 if(*data
.dw
< EAX_ENVIRONMENT_COUNT
)
1892 /* Get the environment index's default and pass it down to
1894 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
1895 pPropData
= (void*)&EnvironmentDefaults
[*data
.dw
];
1896 cbPropData
= sizeof(EnvironmentDefaults
[*data
.dw
]);
1902 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
1903 res
= DSERR_INVALIDPARAM
;
1904 if(cbPropData
>= sizeof(FLOAT
))
1909 } data
= { pPropData
};
1911 if(*data
.fl
>= 1.0f
&& *data
.fl
<= 100.0f
)
1913 double scale
= (*data
.fl
)/This
->eax_prop
.flEnvironmentSize
;
1915 This
->eax_prop
.flEnvironmentSize
= *data
.fl
;
1917 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYTIMESCALE
))
1919 This
->eax_prop
.flDecayTime
*= scale
;
1920 This
->eax_prop
.flDecayTime
= clampF(This
->eax_prop
.flDecayTime
, 0.1f
, 20.0f
);
1922 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSSCALE
))
1924 This
->eax_prop
.lReflections
+= gain_to_mB(1.0/scale
);
1925 This
->eax_prop
.lReflections
= clampI(This
->eax_prop
.lReflections
, -10000, 1000);
1927 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE
))
1929 This
->eax_prop
.flReflectionsDelay
*= scale
;
1930 This
->eax_prop
.flReflectionsDelay
= clampF(This
->eax_prop
.flReflectionsDelay
, 0.0f
, 0.3f
);
1932 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBSCALE
))
1934 This
->eax_prop
.lReverb
+= gain_to_mB(1.0/scale
);
1935 This
->eax_prop
.lReverb
= clampI(This
->eax_prop
.lReverb
, -10000, 2000);
1937 if((This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBDELAYSCALE
))
1939 This
->eax_prop
.flReverbDelay
*= scale
;
1940 This
->eax_prop
.flReverbDelay
= clampF(This
->eax_prop
.flReverbDelay
, 0.0f
, 0.1f
);
1943 /* Pass the updated environment properties down to ALLPARAMETERS */
1944 propid
= DSPROPERTY_EAXLISTENER_ALLPARAMETERS
;
1945 pPropData
= (void*)&This
->eax_prop
;
1946 cbPropData
= sizeof(This
->eax_prop
);
1951 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
1952 res
= DSERR_INVALIDPARAM
;
1953 if(cbPropData
>= sizeof(FLOAT
))
1958 } data
= { pPropData
};
1960 This
->eax_prop
.flEnvironmentDiffusion
= *data
.fl
;
1961 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_DIFFUSION
,
1962 This
->eax_prop
.flEnvironmentDiffusion
);
1965 This
->dirty
.bit
.effect
= 1;
1970 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
1971 res
= DSERR_INVALIDPARAM
;
1972 if(cbPropData
>= sizeof(FLOAT
))
1977 } data
= { pPropData
};
1979 This
->eax_prop
.flAirAbsorptionHF
= *data
.fl
;
1980 This
->ExtAL
->Effectf(This
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
1981 mB_to_gain(This
->eax_prop
.flAirAbsorptionHF
));
1984 This
->dirty
.bit
.effect
= 1;
1989 case DSPROPERTY_EAXLISTENER_FLAGS
:
1990 res
= DSERR_INVALIDPARAM
;
1991 if(cbPropData
>= sizeof(DWORD
))
1996 } data
= { pPropData
};
1998 This
->eax_prop
.dwFlags
= *data
.dw
;
1999 This
->ExtAL
->Effecti(This
->effect
, AL_REVERB_DECAY_HFLIMIT
,
2000 (This
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
2001 AL_TRUE
: AL_FALSE
);
2004 This
->dirty
.bit
.effect
= 1;
2008 FIXME("Unhandled propid: 0x%08"LONGFMT
"x\n", propid
);
2012 if(res
== DS_OK
&& immediate
)
2013 IDirectSound3DListener_CommitDeferredSettings(&This
->IDirectSound3DListener_iface
);
2016 LeaveCriticalSection(This
->crst
);
2019 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2024 static HRESULT WINAPI
DS8PrimaryProp_QuerySupport(IKsPropertySet
*iface
,
2025 REFGUID guidPropSet
, ULONG dwPropID
,
2026 PULONG pTypeSupport
)
2028 DS8Primary
*This
= impl_from_IKsPropertySet(iface
);
2029 HRESULT res
= E_PROP_ID_UNSUPPORTED
;
2031 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2033 EnterCriticalSection(This
->crst
);
2035 if(This
->effect
== 0)
2036 res
= E_PROP_ID_UNSUPPORTED
;
2037 else if(dwPropID
== DSPROPERTY_EAXLISTENER_ALLPARAMETERS
||
2038 dwPropID
== DSPROPERTY_EAXLISTENER_ROOM
||
2039 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMHF
||
2040 dwPropID
== DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
||
2041 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENT
||
2042 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
||
2043 dwPropID
== DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
||
2044 dwPropID
== DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
||
2045 dwPropID
== DSPROPERTY_EAXLISTENER_FLAGS
)
2047 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
|KSPROPERTY_SUPPORT_SET
;
2051 FIXME("Unhandled propid: 0x%08"LONGFMT
"x\n", dwPropID
);
2053 LeaveCriticalSection(This
->crst
);
2056 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2061 static const IKsPropertySetVtbl DS8PrimaryProp_Vtbl
=
2063 DS8PrimaryProp_QueryInterface
,
2064 DS8PrimaryProp_AddRef
,
2065 DS8PrimaryProp_Release
,
2068 DS8PrimaryProp_QuerySupport