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"
47 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
56 #include "dsound_private.h"
58 DEFINE_GUID(CLSID_DirectSoundPrivate
,0x11ab3ec0,0x25ec,0x11d1,0xa4,0xd8,0x00,0xc0,0x4f,0xc2,0x8a,0xca);
60 DEFINE_GUID(DSPROPSETID_DirectSoundDevice
,0x84624f82,0x25ec,0x11d1,0xa4,0xd8,0x00,0xc0,0x4f,0xc2,0x8a,0xca);
62 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM
, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
63 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
65 #ifndef E_PROP_ID_UNSUPPORTED
66 #define E_PROP_ID_UNSUPPORTED ((HRESULT)0x80070490)
71 #ifndef WAVE_FORMAT_IEEE_FLOAT
72 #define WAVE_FORMAT_IEEE_FLOAT 3
75 /* TODO: when bufferlost is set, return from all calls except initialize with
78 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
;
79 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
;
80 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
;
81 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
;
84 static inline DS8Buffer
*impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8
*iface
)
86 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer8_iface
);
88 /* Shares the same vtable */
89 static inline DS8Buffer
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
91 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer8_iface
);
94 static inline DS8Buffer
*impl_from_IDirectSound3DBuffer(IDirectSound3DBuffer
*iface
)
96 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSound3DBuffer_iface
);
99 static inline DS8Buffer
*impl_from_IDirectSoundNotify(IDirectSoundNotify
*iface
)
101 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundNotify_iface
);
104 static inline DS8Buffer
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
106 return CONTAINING_RECORD(iface
, DS8Buffer
, IKsPropertySet_iface
);
110 static void CALLBACK
DS8Buffer_timer(UINT timerID
, UINT msg
, DWORD_PTR dwUser
,
111 DWORD_PTR dw1
, DWORD_PTR dw2
)
117 PostThreadMessageA(dwUser
, WM_USER
, 0, 0);
120 static void DS8Buffer_starttimer(DS8Primary
*prim
)
122 DWORD triggertime
, res
= DS_TIME_RES
;
123 ALint refresh
= FAKE_REFRESH_COUNT
;
129 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
131 alcGetIntegerv(prim
->parent
->device
, ALC_REFRESH
, 1, &refresh
);
132 getALCError(prim
->parent
->device
);
134 triggertime
= 1000 / refresh
/ 2;
135 if(triggertime
< time
.wPeriodMin
)
136 triggertime
= time
.wPeriodMin
;
137 TRACE("Calling timer every %u ms for %i refreshes per second\n", triggertime
, refresh
);
139 if (res
< time
.wPeriodMin
)
140 res
= time
.wPeriodMin
;
141 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
142 WARN("Could not set minimum resolution, don't expect sound\n");
144 prim
->timer_res
= res
;
145 prim
->timer_id
= timeSetEvent(triggertime
, res
, DS8Buffer_timer
, prim
->thread_id
, TIME_PERIODIC
|TIME_KILL_SYNCHRONOUS
);
148 /* Should be called with critsect held and context set.. */
149 static void DS8Buffer_addnotify(DS8Buffer
*buf
)
154 list
= buf
->primary
->notifies
;
155 for(i
= 0; i
< buf
->primary
->nnotifies
; ++i
)
159 ERR("Buffer %p already in notification list\n", buf
);
163 if(buf
->primary
->nnotifies
== buf
->primary
->sizenotifies
)
165 list
= HeapReAlloc(GetProcessHeap(), 0, list
, (buf
->primary
->nnotifies
+ 1) * sizeof(*list
));
168 buf
->primary
->sizenotifies
++;
170 list
[buf
->primary
->nnotifies
++] = buf
;
171 buf
->primary
->notifies
= list
;
175 static const char *get_fmtstr_PCM(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
177 out
->Format
= *format
;
178 out
->Format
.cbSize
= 0;
180 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
181 !prim
->SupportedExt
[EXT_MCFORMATS
])
183 WARN("Multi-channel not available\n");
187 if(format
->wBitsPerSample
== 8)
189 switch(format
->nChannels
)
191 case 1: return "AL_FORMAT_MONO8";
192 case 2: return "AL_FORMAT_STEREO8";
193 case 4: return "AL_FORMAT_QUAD8";
194 case 6: return "AL_FORMAT_51CHN8";
195 case 7: return "AL_FORMAT_61CHN8";
196 case 8: return "AL_FORMAT_71CHN8";
200 else if(format
->wBitsPerSample
== 16)
202 switch(format
->nChannels
)
204 case 1: return "AL_FORMAT_MONO16";
205 case 2: return "AL_FORMAT_STEREO16";
206 case 4: return "AL_FORMAT_QUAD16";
207 case 6: return "AL_FORMAT_51CHN16";
208 case 7: return "AL_FORMAT_61CHN16";
209 case 8: return "AL_FORMAT_71CHN16";
214 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
215 format
->wBitsPerSample
, format
->nChannels
);
218 static ALenum
get_fmt_PCM(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
220 out
->Format
= *format
;
221 out
->Format
.cbSize
= 0;
223 if(format
->wBitsPerSample
== 8)
225 *in_type
= AL_UNSIGNED_BYTE
;
226 switch(format
->nChannels
)
228 case 1: *in_chans
= AL_MONO
;
230 case 2: *in_chans
= AL_STEREO
;
232 case 4: *in_chans
= AL_QUAD
;
234 case 6: *in_chans
= AL_5POINT1
;
236 case 7: *in_chans
= AL_6POINT1
;
238 case 8: *in_chans
= AL_7POINT1
;
243 else if(format
->wBitsPerSample
== 16)
246 switch(format
->nChannels
)
248 case 1: *in_chans
= AL_MONO
;
250 case 2: *in_chans
= AL_STEREO
;
252 case 4: *in_chans
= AL_QUAD
;
254 case 6: *in_chans
= AL_5POINT1
;
255 return AL_5POINT1_16
;
256 case 7: *in_chans
= AL_6POINT1
;
257 return AL_6POINT1_16
;
258 case 8: *in_chans
= AL_7POINT1
;
259 return AL_7POINT1_16
;
263 #if 0 /* Will cause incorrect byte offsets */
264 else if(format
->wBitsPerSample
== 24)
267 switch(format
->nChannels
)
269 case 1: *in_chans
= AL_MONO
;
271 case 2: *in_chans
= AL_STEREO
;
273 case 4: *in_chans
= AL_QUAD
;
275 case 6: *in_chans
= AL_5POINT1
;
276 return AL_5POINT1_32F
;
277 case 7: *in_chans
= AL_6POINT1
;
278 return AL_6POINT1_32F
;
279 case 8: *in_chans
= AL_7POINT1
;
280 return AL_7POINT1_32F
;
285 else if(format
->wBitsPerSample
== 32)
288 switch(format
->nChannels
)
290 case 1: *in_chans
= AL_MONO
;
292 case 2: *in_chans
= AL_STEREO
;
294 case 4: *in_chans
= AL_QUAD
;
296 case 6: *in_chans
= AL_5POINT1
;
297 return AL_5POINT1_32F
;
298 case 7: *in_chans
= AL_6POINT1
;
299 return AL_6POINT1_32F
;
300 case 8: *in_chans
= AL_7POINT1
;
301 return AL_7POINT1_32F
;
306 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
307 format
->wBitsPerSample
, format
->nChannels
);
311 static const char *get_fmtstr_FLOAT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
313 out
->Format
= *format
;
314 out
->Format
.cbSize
= 0;
316 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
317 !prim
->SupportedExt
[EXT_MCFORMATS
])
319 WARN("Multi-channel not available\n");
323 if(format
->wBitsPerSample
== 32 && prim
->SupportedExt
[EXT_FLOAT32
])
325 switch(format
->nChannels
)
327 case 1: return "AL_FORMAT_MONO_FLOAT32";
328 case 2: return "AL_FORMAT_STEREO_FLOAT32";
329 case 4: return "AL_FORMAT_QUAD32";
330 case 6: return "AL_FORMAT_51CHN32";
331 case 7: return "AL_FORMAT_61CHN32";
332 case 8: return "AL_FORMAT_71CHN32";
337 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
338 format
->wBitsPerSample
, format
->nChannels
);
341 static ALenum
get_fmt_FLOAT(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
343 out
->Format
= *format
;
344 out
->Format
.cbSize
= 0;
346 if(format
->wBitsPerSample
== 32)
349 switch(format
->nChannels
)
351 case 1: *in_chans
= AL_MONO
;
353 case 2: *in_chans
= AL_STEREO
;
355 case 4: *in_chans
= AL_QUAD
;
357 case 6: *in_chans
= AL_5POINT1
;
358 return AL_5POINT1_32F
;
359 case 7: *in_chans
= AL_6POINT1
;
360 return AL_6POINT1_32F
;
361 case 8: *in_chans
= AL_7POINT1
;
362 return AL_7POINT1_32F
;
366 #if 0 /* Will cause incorrect byte offsets */
367 else if(format
->wBitsPerSample
== 64)
369 *in_type
= AL_DOUBLE
;
370 switch(format
->nChannels
)
372 case 1: *in_chans
= AL_MONO
;
374 case 2: *in_chans
= AL_STEREO
;
376 case 4: *in_chans
= AL_QUAD
;
378 case 6: *in_chans
= AL_5POINT1
;
379 return AL_5POINT1_32F
;
380 case 7: *in_chans
= AL_6POINT1
;
381 return AL_6POINT1_32F
;
382 case 8: *in_chans
= AL_7POINT1
;
383 return AL_7POINT1_32F
;
389 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
390 format
->wBitsPerSample
, format
->nChannels
);
394 /* Speaker configs */
395 #define MONO SPEAKER_FRONT_CENTER
396 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
397 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
398 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
399 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
400 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
401 #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
403 static const char *get_fmtstr_EXT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
405 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
406 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
408 if(!out
->Samples
.wValidBitsPerSample
)
409 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
410 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
412 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
416 if(out
->dwChannelMask
!= MONO
&& out
->dwChannelMask
!= STEREO
&&
417 !prim
->SupportedExt
[EXT_MCFORMATS
])
419 WARN("Multi-channel not available\n");
423 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
425 if(out
->Samples
.wValidBitsPerSample
== 8)
427 switch(out
->dwChannelMask
)
429 case MONO
: return "AL_FORMAT_MONO8";
430 case STEREO
: return "AL_FORMAT_STEREO8";
431 case REAR
: return "AL_FORMAT_REAR8";
432 case QUAD
: return "AL_FORMAT_QUAD8";
433 case X5DOT1
: return "AL_FORMAT_51CHN8";
434 case X6DOT1
: return "AL_FORMAT_61CHN8";
435 case X7DOT1
: return "AL_FORMAT_71CHN8";
439 else if(out
->Samples
.wValidBitsPerSample
== 16)
441 switch(out
->dwChannelMask
)
443 case MONO
: return "AL_FORMAT_MONO16";
444 case STEREO
: return "AL_FORMAT_STEREO16";
445 case REAR
: return "AL_FORMAT_REAR16";
446 case QUAD
: return "AL_FORMAT_QUAD16";
447 case X5DOT1
: return "AL_FORMAT_51CHN16";
448 case X6DOT1
: return "AL_FORMAT_61CHN16";
449 case X7DOT1
: return "AL_FORMAT_71CHN16";
454 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#x)\n",
455 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
458 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
459 prim
->SupportedExt
[EXT_FLOAT32
])
461 if(out
->Samples
.wValidBitsPerSample
== 32)
463 switch(out
->dwChannelMask
)
465 case MONO
: return "AL_FORMAT_MONO_FLOAT32";
466 case STEREO
: return "AL_FORMAT_STEREO_FLOAT32";
467 case REAR
: return "AL_FORMAT_REAR32";
468 case QUAD
: return "AL_FORMAT_QUAD32";
469 case X5DOT1
: return "AL_FORMAT_51CHN32";
470 case X6DOT1
: return "AL_FORMAT_61CHN32";
471 case X7DOT1
: return "AL_FORMAT_71CHN32";
477 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
481 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#x)\n",
482 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
485 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
486 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
489 static ALenum
get_fmt_EXT(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
491 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
492 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
494 if(!out
->Samples
.wValidBitsPerSample
)
495 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
496 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
498 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
502 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
504 if(out
->Samples
.wValidBitsPerSample
== 8)
506 *in_type
= AL_UNSIGNED_BYTE
;
507 switch(out
->dwChannelMask
)
509 case MONO
: *in_chans
= AL_MONO
;
511 case STEREO
: *in_chans
= AL_STEREO
;
513 case REAR
: *in_chans
= AL_REAR
;
515 case QUAD
: *in_chans
= AL_QUAD
;
517 case X5DOT1
: *in_chans
= AL_5POINT1
;
519 case X6DOT1
: *in_chans
= AL_6POINT1
;
521 case X7DOT1
: *in_chans
= AL_7POINT1
;
526 else if(out
->Samples
.wValidBitsPerSample
== 16)
529 switch(out
->dwChannelMask
)
531 case MONO
: *in_chans
= AL_MONO
;
533 case STEREO
: *in_chans
= AL_STEREO
;
535 case REAR
: *in_chans
= AL_REAR
;
537 case QUAD
: *in_chans
= AL_QUAD
;
539 case X5DOT1
: *in_chans
= AL_5POINT1
;
540 return AL_5POINT1_16
;
541 case X6DOT1
: *in_chans
= AL_6POINT1
;
542 return AL_6POINT1_16
;
543 case X7DOT1
: *in_chans
= AL_7POINT1
;
544 return AL_7POINT1_16
;
549 else if(out
->Samples
.wValidBitsPerSample
== 24)
552 switch(out
->dwChannelMask
)
554 case MONO
: *in_chans
= AL_MONO
;
556 case STEREO
: *in_chans
= AL_STEREO
;
558 case REAR
: *in_chans
= AL_REAR
;
560 case QUAD
: *in_chans
= AL_QUAD
;
562 case X5DOT1
: *in_chans
= AL_5POINT1
;
563 return AL_5POINT1_32F
;
564 case X6DOT1
: *in_chans
= AL_6POINT1
;
565 return AL_6POINT1_32F
;
566 case X7DOT1
: *in_chans
= AL_7POINT1
;
567 return AL_7POINT1_32F
;
572 else if(out
->Samples
.wValidBitsPerSample
== 32)
575 switch(out
->dwChannelMask
)
577 case MONO
: *in_chans
= AL_MONO
;
579 case STEREO
: *in_chans
= AL_STEREO
;
581 case REAR
: *in_chans
= AL_REAR
;
583 case QUAD
: *in_chans
= AL_QUAD
;
585 case X5DOT1
: *in_chans
= AL_5POINT1
;
586 return AL_5POINT1_32F
;
587 case X6DOT1
: *in_chans
= AL_6POINT1
;
588 return AL_6POINT1_32F
;
589 case X7DOT1
: *in_chans
= AL_7POINT1
;
590 return AL_7POINT1_32F
;
595 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#x)\n",
596 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
599 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
601 if(out
->Samples
.wValidBitsPerSample
== 32)
604 switch(out
->dwChannelMask
)
606 case MONO
: *in_chans
= AL_MONO
;
608 case STEREO
: *in_chans
= AL_STEREO
;
610 case REAR
: *in_chans
= AL_REAR
;
612 case QUAD
: *in_chans
= AL_QUAD
;
614 case X5DOT1
: *in_chans
= AL_5POINT1
;
615 return AL_5POINT1_32F
;
616 case X6DOT1
: *in_chans
= AL_6POINT1
;
617 return AL_6POINT1_32F
;
618 case X7DOT1
: *in_chans
= AL_7POINT1
;
619 return AL_7POINT1_32F
;
624 else if(out
->Samples
.wValidBitsPerSample
== 64)
626 *in_type
= AL_DOUBLE
;
627 switch(out
->dwChannelMask
)
629 case MONO
: *in_chans
= AL_MONO
;
631 case STEREO
: *in_chans
= AL_STEREO
;
633 case REAR
: *in_chans
= AL_REAR
;
635 case QUAD
: *in_chans
= AL_QUAD
;
637 case X5DOT1
: *in_chans
= AL_5POINT1
;
638 return AL_5POINT1_32F
;
639 case X6DOT1
: *in_chans
= AL_6POINT1
;
640 return AL_6POINT1_32F
;
641 case X7DOT1
: *in_chans
= AL_7POINT1
;
642 return AL_7POINT1_32F
;
649 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
653 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#x)\n",
654 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
657 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
658 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
662 static void DS8Data_Release(DS8Data
*This
);
663 static HRESULT
DS8Data_Create(DS8Data
**ppv
, const DSBUFFERDESC
*desc
, DS8Primary
*prim
)
665 HRESULT hr
= DSERR_INVALIDPARAM
;
666 const WAVEFORMATEX
*format
;
669 format
= desc
->lpwfxFormat
;
670 TRACE("Requested buffer format:\n"
671 " FormatTag = 0x%04x\n"
673 " SamplesPerSec = %u\n"
674 " AvgBytesPerSec = %u\n"
676 " BitsPerSample = %d\n",
677 format
->wFormatTag
, format
->nChannels
,
678 format
->nSamplesPerSec
, format
->nAvgBytesPerSec
,
679 format
->nBlockAlign
, format
->wBitsPerSample
);
681 if(format
->nBlockAlign
== 0)
683 WARN("Invalid BlockAlign specified\n");
684 return DSERR_INVALIDPARAM
;
687 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
688 * will need the EAX-RAM extension. Currently, we just tell the app it
689 * gets what it wanted. */
690 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
));
692 return E_OUTOFMEMORY
;
695 pBuffer
->dsbflags
= desc
->dwFlags
;
696 if((pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
)) == (DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
))
698 WARN("Hardware and software location requested\n");
701 if(!(pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCDEFER
)))
702 pBuffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
704 pBuffer
->buf_size
= desc
->dwBufferBytes
+ format
->nBlockAlign
- 1;
705 pBuffer
->buf_size
-= pBuffer
->buf_size
%format
->nBlockAlign
;
707 hr
= DSERR_BUFFERTOOSMALL
;
708 if(pBuffer
->buf_size
< DSBSIZE_MIN
)
711 hr
= DSERR_INVALIDPARAM
;
712 if(pBuffer
->buf_size
> DSBSIZE_MAX
)
715 pBuffer
->numsegs
= 1;
716 pBuffer
->segsize
= pBuffer
->buf_size
;
717 pBuffer
->lastsegsize
= pBuffer
->buf_size
;
719 if(!prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
723 if(!(pBuffer
->dsbflags
&DSBCAPS_STATIC
) && !prim
->ExtAL
.BufferSubData
&&
724 !prim
->ExtAL
.BufferDataStatic
)
726 ALCint refresh
= FAKE_REFRESH_COUNT
;
729 alcGetIntegerv(prim
->parent
->device
, ALC_REFRESH
, 1, &refresh
);
730 getALCError(prim
->parent
->device
);
732 newSize
= format
->nAvgBytesPerSec
/refresh
+ format
->nBlockAlign
- 1;
733 newSize
-= newSize
%format
->nBlockAlign
;
735 /* Make sure enough buffers are available */
736 if(newSize
> pBuffer
->buf_size
/(QBUFFERS
+2))
737 ERR("Buffer segments too large to stream (%u for %u)!\n",
738 newSize
, pBuffer
->buf_size
);
741 pBuffer
->numsegs
= pBuffer
->buf_size
/newSize
;
742 pBuffer
->segsize
= newSize
;
743 pBuffer
->lastsegsize
= pBuffer
->buf_size
- (newSize
*(pBuffer
->numsegs
-1));
744 TRACE("New streaming buffer (%u chunks, %u : %u sizes)\n",
745 pBuffer
->numsegs
, pBuffer
->segsize
, pBuffer
->lastsegsize
);
749 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
750 fmt_str
= get_fmtstr_PCM(prim
, format
, &pBuffer
->format
);
751 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
752 fmt_str
= get_fmtstr_FLOAT(prim
, format
, &pBuffer
->format
);
753 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
755 const WAVEFORMATEXTENSIBLE
*wfe
;
757 hr
= DSERR_CONTROLUNAVAIL
;
758 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
759 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
762 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
763 TRACE("Extensible values:\n"
765 " ChannelMask = 0x%x\n"
767 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
768 debugstr_guid(&wfe
->SubFormat
));
770 fmt_str
= get_fmtstr_EXT(prim
, format
, &pBuffer
->format
);
773 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
775 hr
= DSERR_INVALIDCALL
;
779 pBuffer
->buf_format
= alGetEnumValue(fmt_str
);
780 if(alGetError() != AL_NO_ERROR
|| pBuffer
->buf_format
== 0 ||
781 pBuffer
->buf_format
== -1)
783 WARN("Could not get OpenAL format from %s\n", fmt_str
);
789 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
790 pBuffer
->buf_format
= get_fmt_PCM(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
791 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
792 pBuffer
->buf_format
= get_fmt_FLOAT(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
793 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
795 const WAVEFORMATEXTENSIBLE
*wfe
;
797 hr
= DSERR_CONTROLUNAVAIL
;
798 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
799 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
802 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
803 TRACE("Extensible values:\n"
805 " ChannelMask = 0x%x\n"
807 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
808 debugstr_guid(&wfe
->SubFormat
));
810 pBuffer
->buf_format
= get_fmt_EXT(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
813 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
815 hr
= DSERR_INVALIDCALL
;
816 if(prim
->ExtAL
.IsBufferFormatSupportedSOFT(pBuffer
->buf_format
) == AL_FALSE
)
818 WARN("Unsupported OpenAL format: 0x%x\n", pBuffer
->buf_format
);
824 pBuffer
->buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
->buffers
)*pBuffer
->numsegs
);
825 pBuffer
->data
= HeapAlloc(GetProcessHeap(), 0, pBuffer
->buf_size
);
826 if(!pBuffer
->buffers
|| !pBuffer
->data
)
829 alGenBuffers(pBuffer
->numsegs
, pBuffer
->buffers
);
836 DS8Data_Release(pBuffer
);
840 static void DS8Data_AddRef(DS8Data
*data
)
842 InterlockedIncrement(&data
->ref
);
845 /* This function is always called with the device lock held */
846 static void DS8Data_Release(DS8Data
*This
)
848 if(InterlockedDecrement(&This
->ref
)) return;
850 TRACE("Deleting %p\n", This
);
851 if (This
->buffers
&& This
->buffers
[0])
853 alDeleteBuffers(This
->numsegs
, This
->buffers
);
856 HeapFree(GetProcessHeap(), 0, This
->buffers
);
857 HeapFree(GetProcessHeap(), 0, This
->data
);
858 HeapFree(GetProcessHeap(), 0, This
);
861 HRESULT
DS8Buffer_Create(DS8Buffer
**ppv
, DS8Primary
*parent
, IDirectSoundBuffer
*orig
)
863 HRESULT hr
= DSERR_OUTOFMEMORY
;
868 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
871 This
->IDirectSoundBuffer8_iface
.lpVtbl
= (IDirectSoundBuffer8Vtbl
*)&DS8Buffer_Vtbl
;
872 This
->IDirectSound3DBuffer_iface
.lpVtbl
= (IDirectSound3DBufferVtbl
*)&DS8Buffer3d_Vtbl
;
873 This
->IDirectSoundNotify_iface
.lpVtbl
= (IDirectSoundNotifyVtbl
*)&DS8BufferNot_Vtbl
;
874 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8BufferProp_Vtbl
;
876 This
->primary
= parent
;
877 This
->ctx
= parent
->ctx
;
878 This
->ExtAL
= &parent
->ExtAL
;
879 This
->crst
= &parent
->crst
;
880 This
->ref
= This
->all_ref
= 1;
884 DS8Buffer
*org
= impl_from_IDirectSoundBuffer(orig
);
885 hr
= DSERR_BUFFERLOST
;
888 DS8Data_AddRef(org
->buffer
);
889 This
->buffer
= org
->buffer
;
892 /* Append to buffer list */
893 bufs
= parent
->buffers
;
894 if(parent
->nbuffers
== parent
->sizebuffers
)
896 bufs
= HeapReAlloc(GetProcessHeap(), 0, bufs
, sizeof(*bufs
)*(1+parent
->nbuffers
));
897 hr
= DSERR_OUTOFMEMORY
;
899 parent
->sizebuffers
++;
901 parent
->buffers
= bufs
;
902 bufs
[parent
->nbuffers
++] = This
;
904 /* Disable until initialized.. */
905 This
->ds3dmode
= DS3DMODE_DISABLE
;
911 DS8Buffer_Destroy(This
);
915 void DS8Buffer_Destroy(DS8Buffer
*This
)
917 DS8Primary
*prim
= This
->primary
;
920 TRACE("Destroying %p\n", This
);
922 EnterCriticalSection(&prim
->crst
);
923 /* Remove from list, if in list */
924 for(idx
= 0;idx
< prim
->nnotifies
;++idx
)
926 if(This
== prim
->notifies
[idx
])
928 prim
->notifies
[idx
] = prim
->notifies
[--prim
->nnotifies
];
932 for(idx
= 0;idx
< prim
->nbuffers
;++idx
)
934 if(prim
->buffers
[idx
] == This
)
936 prim
->buffers
[idx
] = prim
->buffers
[--prim
->nbuffers
];
941 setALContext(This
->ctx
);
946 alSourceStop(This
->source
);
947 alSourcei(This
->source
, AL_BUFFER
, 0);
950 sources
= prim
->sources
;
951 if(prim
->nsources
== prim
->sizesources
)
953 sources
= HeapReAlloc(GetProcessHeap(), 0, sources
, sizeof(*sources
)*(prim
->nsources
+1));
955 alDeleteSources(1, &This
->source
);
961 sources
[prim
->nsources
++] = This
->source
;
962 prim
->sources
= sources
;
966 LeaveCriticalSection(&prim
->crst
);
969 DS8Data_Release(This
->buffer
);
973 HeapFree(GetProcessHeap(), 0, This
->notify
);
974 HeapFree(GetProcessHeap(), 0, This
);
978 static HRESULT WINAPI
DS8Buffer_QueryInterface(IDirectSoundBuffer8
*iface
, REFIID riid
, void **ppv
)
980 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
982 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
985 if(IsEqualIID(riid
, &IID_IUnknown
) ||
986 IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
987 *ppv
= &This
->IDirectSoundBuffer8_iface
;
988 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer8
))
990 if(This
->primary
->parent
->is_8
)
991 *ppv
= &This
->IDirectSoundBuffer8_iface
;
993 else if(IsEqualIID(riid
, &IID_IDirectSound3DBuffer
))
995 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
996 *ppv
= &This
->IDirectSound3DBuffer_iface
;
998 else if(IsEqualIID(riid
, &IID_IDirectSoundNotify
))
1000 if((This
->buffer
->dsbflags
&DSBCAPS_CTRLPOSITIONNOTIFY
))
1001 *ppv
= &This
->IDirectSoundNotify_iface
;
1003 else if(IsEqualIID(riid
, &IID_IKsPropertySet
))
1004 *ppv
= &This
->IKsPropertySet_iface
;
1006 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
1010 IUnknown_AddRef((IUnknown
*)*ppv
);
1014 return E_NOINTERFACE
;
1017 static ULONG WINAPI
DS8Buffer_AddRef(IDirectSoundBuffer8
*iface
)
1019 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1022 InterlockedIncrement(&This
->all_ref
);
1023 ret
= InterlockedIncrement(&This
->ref
);
1024 TRACE("new refcount %d\n", ret
);
1029 static ULONG WINAPI
DS8Buffer_Release(IDirectSoundBuffer8
*iface
)
1031 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1034 ret
= InterlockedDecrement(&This
->ref
);
1035 TRACE("new refcount %d\n", ret
);
1036 if(InterlockedDecrement(&This
->all_ref
) == 0)
1037 DS8Buffer_Destroy(This
);
1042 static HRESULT WINAPI
DS8Buffer_GetCaps(IDirectSoundBuffer8
*iface
, DSBCAPS
*caps
)
1044 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1046 TRACE("(%p)->(%p)\n", iface
, caps
);
1048 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
1050 WARN("Invalid DSBCAPS (%p, %u)\n", caps
, (caps
? caps
->dwSize
: 0));
1051 return DSERR_INVALIDPARAM
;
1054 caps
->dwFlags
= This
->buffer
->dsbflags
;
1055 caps
->dwBufferBytes
= This
->buffer
->buf_size
;
1056 caps
->dwUnlockTransferRate
= 4096;
1057 caps
->dwPlayCpuOverhead
= 0;
1061 static HRESULT WINAPI
DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD
*playpos
, DWORD
*curpos
)
1063 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1064 WAVEFORMATEX
*format
= &This
->buffer
->format
.Format
;
1065 UINT writecursor
, pos
;
1067 TRACE("(%p)->(%p, %p)\n", iface
, playpos
, curpos
);
1069 EnterCriticalSection(This
->crst
);
1070 setALContext(This
->ctx
);
1072 if(This
->buffer
->numsegs
> 1)
1074 ALint queued
= QBUFFERS
;
1075 alGetSourcei(This
->source
, AL_BUFFERS_QUEUED
, &queued
);
1078 pos
= (This
->curidx
+This
->buffer
->numsegs
-queued
)%This
->buffer
->numsegs
;
1079 pos
*= This
->buffer
->segsize
;
1080 writecursor
= This
->curidx
* This
->buffer
->segsize
;
1082 else if(This
->ExtAL
->BufferSubData
|| This
->ExtAL
->BufferSamplesSOFT
)
1084 ALint rwpos
[2] = { 0, 0 };
1086 alGetSourceiv(This
->source
, AL_BYTE_RW_OFFSETS_SOFT
, rwpos
);
1090 writecursor
= rwpos
[1];
1097 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
1098 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
1102 if(status
== AL_PLAYING
)
1104 writecursor
= format
->nSamplesPerSec
/ 100;
1105 writecursor
*= format
->nBlockAlign
;
1109 writecursor
= (writecursor
+ pos
) % This
->buffer
->buf_size
;
1111 TRACE("%p Play pos = %u, write pos = %u\n", This
, pos
, writecursor
);
1112 if(pos
>= This
->buffer
->buf_size
)
1114 ERR("playpos >= buf_size\n");
1115 pos
%= This
->buffer
->buf_size
;
1117 if(writecursor
>= This
->buffer
->buf_size
)
1119 ERR("writepos >= buf_size\n");
1120 writecursor
%= This
->buffer
->buf_size
;
1123 if(playpos
) *playpos
= pos
;
1124 if(curpos
) *curpos
= writecursor
;
1127 LeaveCriticalSection(This
->crst
);
1132 static HRESULT WINAPI
DS8Buffer_GetFormat(IDirectSoundBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
1134 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1138 TRACE("(%p)->(%p, %u, %p)\n", iface
, wfx
, allocated
, written
);
1140 if(!wfx
&& !written
)
1142 WARN("Cannot report format or format size\n");
1143 return DSERR_INVALIDPARAM
;
1146 EnterCriticalSection(This
->crst
);
1147 size
= sizeof(This
->buffer
->format
.Format
) + This
->buffer
->format
.Format
.cbSize
;
1150 if(allocated
< size
)
1151 hr
= DSERR_INVALIDPARAM
;
1153 memcpy(wfx
, &This
->buffer
->format
.Format
, size
);
1157 LeaveCriticalSection(This
->crst
);
1162 static HRESULT WINAPI
DS8Buffer_GetVolume(IDirectSoundBuffer8
*iface
, LONG
*vol
)
1164 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1167 TRACE("(%p)->(%p)\n", iface
, vol
);
1171 WARN("Invalid pointer\n");
1172 return DSERR_INVALIDPARAM
;
1175 EnterCriticalSection(This
->crst
);
1177 hr
= DSERR_CONTROLUNAVAIL
;
1178 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1179 WARN("Volume control not set\n");
1182 ALfloat gain
= 1.0f
;
1184 setALContext(This
->ctx
);
1185 alGetSourcef(This
->source
, AL_GAIN
, &gain
);
1189 *vol
= gain_to_mB(gain
);
1190 *vol
= min(*vol
, DSBVOLUME_MAX
);
1191 *vol
= max(*vol
, DSBVOLUME_MIN
);
1196 LeaveCriticalSection(This
->crst
);
1200 static HRESULT WINAPI
DS8Buffer_GetPan(IDirectSoundBuffer8
*iface
, LONG
*pan
)
1202 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1205 TRACE("(%p)->(%p)\n", iface
, pan
);
1209 WARN("Invalid pointer\n");
1210 return DSERR_INVALIDPARAM
;
1213 EnterCriticalSection(This
->crst
);
1215 hr
= DSERR_CONTROLUNAVAIL
;
1216 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1217 WARN("Panning control not set\n");
1222 setALContext(This
->ctx
);
1223 alGetSourcefv(This
->source
, AL_POSITION
, pos
);
1227 *pan
= (LONG
)((pos
[0]+1.0) * (DSBPAN_RIGHT
-DSBPAN_LEFT
) / 2.0 + 0.5) + DSBPAN_LEFT
;
1228 *pan
= min(*pan
, DSBPAN_RIGHT
);
1229 *pan
= max(*pan
, DSBPAN_LEFT
);
1234 LeaveCriticalSection(This
->crst
);
1238 static HRESULT WINAPI
DS8Buffer_GetFrequency(IDirectSoundBuffer8
*iface
, DWORD
*freq
)
1240 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1243 TRACE("(%p)->(%p)\n", iface
, freq
);
1247 WARN("Invalid pointer\n");
1248 return DSERR_INVALIDPARAM
;
1251 EnterCriticalSection(This
->crst
);
1253 hr
= DSERR_CONTROLUNAVAIL
;
1254 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1255 WARN("Frequency control not set\n");
1258 ALfloat pitch
= 1.0f
;
1260 setALContext(This
->ctx
);
1261 alGetSourcefv(This
->source
, AL_PITCH
, &pitch
);
1265 *freq
= (DWORD
)(This
->buffer
->format
.Format
.nSamplesPerSec
* pitch
);
1270 LeaveCriticalSection(This
->crst
);
1274 static HRESULT WINAPI
DS8Buffer_GetStatus(IDirectSoundBuffer8
*iface
, DWORD
*status
)
1276 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1277 ALint state
, looping
;
1279 TRACE("(%p)->(%p)\n", iface
, status
);
1283 WARN("Invalid pointer\n");
1284 return DSERR_INVALIDPARAM
;
1287 EnterCriticalSection(This
->crst
);
1289 setALContext(This
->ctx
);
1290 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1291 looping
= This
->islooping
;
1292 if(This
->buffer
->numsegs
== 1)
1293 alGetSourcei(This
->source
, AL_LOOPING
, &looping
);
1294 else if(state
!= AL_PLAYING
)
1295 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1300 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1302 if((This
->buffer
->dsbflags
&DSBCAPS_LOCSOFTWARE
))
1303 *status
|= DSBSTATUS_LOCSOFTWARE
;
1304 else if((This
->buffer
->dsbflags
&DSBCAPS_LOCHARDWARE
))
1305 *status
|= DSBSTATUS_LOCHARDWARE
;
1307 if(state
== AL_PLAYING
)
1308 *status
|= DSBSTATUS_PLAYING
| (looping
? DSBSTATUS_LOOPING
: 0);
1310 LeaveCriticalSection(This
->crst
);
1315 static HRESULT WINAPI
DS8Buffer_Initialize(IDirectSoundBuffer8
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
1317 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1318 DS3DBUFFER
*ds3dbuffer
;
1321 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
1323 EnterCriticalSection(This
->crst
);
1324 setALContext(This
->ctx
);
1326 hr
= DSERR_ALREADYINITIALIZED
;
1332 hr
= DSERR_INVALIDPARAM
;
1335 WARN("Missing DSound buffer description\n");
1338 if(!desc
->lpwfxFormat
)
1340 WARN("Missing buffer format (%p)\n", This
);
1343 if((desc
->dwFlags
&DSBCAPS_CTRL3D
) && desc
->lpwfxFormat
->nChannels
!= 1)
1345 if(This
->primary
->parent
->is_8
)
1347 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
1349 WARN("Can't create multi-channel 3D buffers\n");
1352 ERR("Multi-channel 3D sounds are not spatialized\n");
1355 hr
= DS8Data_Create(&This
->buffer
, desc
, This
->primary
);
1360 DS8Data
*buf
= This
->buffer
;
1362 if(buf
->in_type
== AL_UNSIGNED_BYTE
)
1363 memset(buf
->data
, 0x80, buf
->buf_size
);
1365 memset(buf
->data
, 0x00, buf
->buf_size
);
1367 if(This
->ExtAL
->BufferDataStatic
)
1368 This
->ExtAL
->BufferDataStatic(buf
->buffers
[0], buf
->buf_format
,
1369 buf
->data
, buf
->buf_size
,
1370 buf
->format
.Format
.nSamplesPerSec
);
1371 else if(This
->ExtAL
->BufferSamplesSOFT
)
1372 This
->ExtAL
->BufferSamplesSOFT(buf
->buffers
[0],
1373 buf
->format
.Format
.nSamplesPerSec
, buf
->buf_format
,
1374 buf
->buf_size
/buf
->format
.Format
.nBlockAlign
,
1375 buf
->in_chans
, buf
->in_type
, buf
->data
);
1376 else if(This
->ExtAL
->BufferSubData
)
1377 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1378 buf
->data
, buf
->buf_size
,
1379 buf
->format
.Format
.nSamplesPerSec
);
1385 if(This
->primary
->nsources
)
1387 This
->source
= This
->primary
->sources
[--This
->primary
->nsources
];
1388 alSourcef(This
->source
, AL_GAIN
, 1.0f
);
1389 alSourcef(This
->source
, AL_PITCH
, 1.0f
);
1394 alGenSources(1, &This
->source
);
1395 if(alGetError() != AL_NO_ERROR
)
1399 ds3dbuffer
= &This
->ds3dbuffer
;
1400 ds3dbuffer
->dwSize
= sizeof(*ds3dbuffer
);
1401 ds3dbuffer
->vPosition
.x
= 0.0;
1402 ds3dbuffer
->vPosition
.y
= 0.0;
1403 ds3dbuffer
->vPosition
.z
= 0.0;
1404 ds3dbuffer
->vVelocity
.x
= 0.0;
1405 ds3dbuffer
->vVelocity
.y
= 0.0;
1406 ds3dbuffer
->vVelocity
.z
= 0.0;
1407 ds3dbuffer
->dwInsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1408 ds3dbuffer
->dwOutsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1409 ds3dbuffer
->vConeOrientation
.x
= 0.0;
1410 ds3dbuffer
->vConeOrientation
.y
= 0.0;
1411 ds3dbuffer
->vConeOrientation
.z
= 1.0;
1412 ds3dbuffer
->lConeOutsideVolume
= DS3D_DEFAULTCONEOUTSIDEVOLUME
;
1413 ds3dbuffer
->flMinDistance
= DS3D_DEFAULTMINDISTANCE
;
1414 ds3dbuffer
->flMaxDistance
= DS3D_DEFAULTMAXDISTANCE
;
1415 ds3dbuffer
->dwMode
= DS3DMODE_NORMAL
;
1417 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
1419 if(This
->primary
->auxslot
!= 0)
1421 alSource3i(This
->source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1425 hr
= IDirectSound3DBuffer_SetAllParameters(&This
->IDirectSound3DBuffer_iface
, ds3dbuffer
, DS3D_IMMEDIATE
);
1428 ERR("SetAllParameters failed\n");
1434 ALuint source
= This
->source
;
1436 if(This
->primary
->auxslot
!= 0)
1438 /* Simple hack to make reverb affect non-3D sounds too */
1439 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1440 /*alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);*/
1443 /* Non-3D sources aren't distance attenuated */
1444 This
->ds3dmode
= DS3DMODE_DISABLE
;
1445 alSource3f(source
, AL_POSITION
, 0.0f
, 1.0f
, 0.0f
);
1446 alSource3f(source
, AL_VELOCITY
, 0.0f
, 0.0f
, 0.0f
);
1447 alSource3f(source
, AL_DIRECTION
, 0.0f
, 0.0f
, 0.0f
);
1448 alSourcef(source
, AL_CONE_OUTER_GAIN
, 1.0f
);
1449 alSourcef(source
, AL_REFERENCE_DISTANCE
, 1.0f
);
1450 alSourcef(source
, AL_MAX_DISTANCE
, 1000.0f
);
1451 alSourcef(source
, AL_ROLLOFF_FACTOR
, 0.0f
);
1452 alSourcei(source
, AL_CONE_INNER_ANGLE
, 360);
1453 alSourcei(source
, AL_CONE_OUTER_ANGLE
, 360);
1454 alSourcei(source
, AL_SOURCE_RELATIVE
, AL_TRUE
);
1461 LeaveCriticalSection(This
->crst
);
1466 static HRESULT WINAPI
DS8Buffer_Lock(IDirectSoundBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1468 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1472 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, 0x%x)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1476 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
1477 return DSERR_INVALIDPARAM
;
1480 EnterCriticalSection(This
->crst
);
1481 setALContext(This
->ctx
);
1485 if(ptr2
) *ptr2
= NULL
;
1488 hr
= DSERR_INVALIDPARAM
;
1489 if((flags
&DSBLOCK_FROMWRITECURSOR
))
1490 DS8Buffer_GetCurrentPosition(iface
, NULL
, &ofs
);
1491 else if(ofs
>= This
->buffer
->buf_size
)
1493 WARN("Invalid ofs %u\n", ofs
);
1496 if((flags
&DSBLOCK_ENTIREBUFFER
))
1497 bytes
= This
->buffer
->buf_size
;
1498 else if(bytes
> This
->buffer
->buf_size
)
1500 WARN("Invalid size %u\n", bytes
);
1504 *ptr1
= This
->buffer
->data
+ ofs
;
1505 if(ofs
+bytes
>= This
->buffer
->buf_size
)
1507 *len1
= This
->buffer
->buf_size
- ofs
;
1508 remain
= bytes
- *len1
;
1516 This
->buffer
->locked
= TRUE
;
1518 if(ptr2
&& len2
&& remain
)
1520 *ptr2
= This
->buffer
->data
;
1527 LeaveCriticalSection(This
->crst
);
1531 static HRESULT WINAPI
DS8Buffer_Play(IDirectSoundBuffer8
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1533 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1534 ALint type
, state
= AL_STOPPED
;
1538 TRACE("%p\n", This
);
1540 EnterCriticalSection(This
->crst
);
1541 setALContext(This
->ctx
);
1543 hr
= DSERR_BUFFERLOST
;
1544 if(This
->bufferlost
)
1546 WARN("Buffer %p lost\n", This
);
1550 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1552 if(!(This
->buffer
->dsbflags
&(DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCSOFTWARE
)))
1554 if(flags
& DSBPLAY_LOCSOFTWARE
)
1555 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1557 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1562 ERR("Invalid priority set for non-deferred buffer %p, %u!\n", This
->buffer
, prio
);
1563 hr
= DSERR_INVALIDPARAM
;
1567 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1568 if(This
->buffer
->numsegs
> 1)
1570 This
->islooping
= !!(flags
&DSBPLAY_LOOPING
);
1571 if(state
!= AL_PLAYING
&& This
->isplaying
)
1576 alGetSourcei(This
->source
, AL_SOURCE_TYPE
, &type
);
1577 alSourcei(This
->source
, AL_LOOPING
, (flags
&DSBPLAY_LOOPING
) ? AL_TRUE
: AL_FALSE
);
1582 if(state
== AL_PLAYING
)
1585 /* alSourceQueueBuffers will implicitly set type to streaming */
1586 if(This
->buffer
->numsegs
== 1)
1588 if(type
!= AL_STATIC
)
1589 alSourcei(This
->source
, AL_BUFFER
, This
->buffer
->buffers
[0]);
1590 alSourcePlay(This
->source
);
1592 if(alGetError() != AL_NO_ERROR
)
1594 ERR("Couldn't start source\n");
1595 This
->curidx
= (This
->buffer
->numsegs
-1+This
->curidx
)%This
->buffer
->numsegs
;
1596 alSourcei(This
->source
, AL_BUFFER
, 0);
1601 This
->isplaying
= TRUE
;
1605 DS8Buffer_addnotify(This
);
1606 DS8Buffer_starttimer(This
->primary
);
1608 else if(This
->buffer
->numsegs
> 1)
1609 DS8Buffer_starttimer(This
->primary
);
1613 LeaveCriticalSection(This
->crst
);
1617 static HRESULT WINAPI
DS8Buffer_SetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD pos
)
1619 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1621 TRACE("%p\n", This
);
1623 EnterCriticalSection(This
->crst
);
1624 setALContext(This
->ctx
);
1626 hr
= DSERR_INVALIDPARAM
;
1627 if(pos
>= This
->buffer
->buf_size
)
1630 if(This
->buffer
->numsegs
> 1)
1632 DS8Data
*buf
= This
->buffer
;
1633 This
->curidx
= pos
/buf
->segsize
;
1634 if(This
->curidx
>= buf
->numsegs
)
1635 This
->curidx
= buf
->numsegs
- 1;
1638 /* Perform a flush, so the next timer update will restart at the
1639 * proper position */
1640 alSourceStop(This
->source
);
1641 alSourcei(This
->source
, AL_BUFFER
, 0);
1646 alSourcei(This
->source
, AL_BYTE_OFFSET
, pos
);
1647 This
->lastpos
= pos
;
1652 LeaveCriticalSection(This
->crst
);
1656 static HRESULT WINAPI
DS8Buffer_SetFormat(IDirectSoundBuffer8
*iface
, const WAVEFORMATEX
*wfx
)
1658 /* This call only works on primary buffers */
1659 WARN("(%p)->(%p)\n", iface
, wfx
);
1660 return DSERR_INVALIDCALL
;
1663 static HRESULT WINAPI
DS8Buffer_SetVolume(IDirectSoundBuffer8
*iface
, LONG vol
)
1665 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1668 TRACE("(%p)->(%d)\n", iface
, vol
);
1670 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
1672 WARN("Invalid volume (%d)\n", vol
);
1673 return DSERR_INVALIDPARAM
;
1676 EnterCriticalSection(This
->crst
);
1677 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1678 hr
= DSERR_CONTROLUNAVAIL
;
1681 ALfloat fvol
= mB_to_gain(vol
);
1682 setALContext(This
->ctx
);
1683 alSourcef(This
->source
, AL_GAIN
, fvol
);
1686 LeaveCriticalSection(This
->crst
);
1691 static HRESULT WINAPI
DS8Buffer_SetPan(IDirectSoundBuffer8
*iface
, LONG pan
)
1693 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1696 TRACE("(%p)->(%d)\n", iface
, pan
);
1698 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
1700 WARN("invalid parameter: pan = %d\n", pan
);
1701 return DSERR_INVALIDPARAM
;
1704 EnterCriticalSection(This
->crst
);
1705 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1706 hr
= DSERR_CONTROLUNAVAIL
;
1710 pos
[0] = (pan
-DSBPAN_LEFT
) * 2.0 / (ALfloat
)(DSBPAN_RIGHT
-DSBPAN_LEFT
) - 1.0;
1711 /* NOTE: Strict movement along the X plane can cause the sound to jump
1712 * between left and right sharply. Using a curved path helps smooth it
1714 pos
[1] = sqrt(1.0 - pos
[0]*pos
[0]);
1717 setALContext(This
->ctx
);
1718 alSourcefv(This
->source
, AL_POSITION
, pos
);
1722 if(pan
!= 0 && This
->buffer
->format
.Format
.nChannels
> 1)
1723 FIXME("Panning for multi-channel buffers is not supported\n");
1725 LeaveCriticalSection(This
->crst
);
1730 static HRESULT WINAPI
DS8Buffer_SetFrequency(IDirectSoundBuffer8
*iface
, DWORD freq
)
1732 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1735 TRACE("(%p)->(%u)\n", iface
, freq
);
1737 if(freq
< DSBFREQUENCY_MIN
|| freq
> DSBFREQUENCY_MAX
)
1739 WARN("invalid parameter: freq = %d\n", freq
);
1740 return DSERR_INVALIDPARAM
;
1743 EnterCriticalSection(This
->crst
);
1744 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1745 hr
= DSERR_CONTROLUNAVAIL
;
1748 ALfloat pitch
= 1.0f
;
1749 if(freq
!= DSBFREQUENCY_ORIGINAL
)
1750 pitch
= freq
/ (ALfloat
)This
->buffer
->format
.Format
.nSamplesPerSec
;
1752 setALContext(This
->ctx
);
1753 alSourcef(This
->source
, AL_PITCH
, pitch
);
1757 LeaveCriticalSection(This
->crst
);
1761 static HRESULT WINAPI
DS8Buffer_Stop(IDirectSoundBuffer8
*iface
)
1763 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1766 TRACE("(%p)->()\n", iface
);
1768 EnterCriticalSection(This
->crst
);
1769 setALContext(This
->ctx
);
1771 alSourcePause(This
->source
);
1773 /* Mac OS X doesn't immediately report state change
1774 * if Play() is immediately called after Stop, this can be fatal,
1775 * the buffer would never be restarted
1779 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1780 if(state
!= AL_PLAYING
)
1785 This
->isplaying
= FALSE
;
1788 LeaveCriticalSection(This
->crst
);
1793 static HRESULT WINAPI
DS8Buffer_Unlock(IDirectSoundBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1795 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1796 DS8Data
*buf
= This
->buffer
;
1797 DWORD bufsize
= buf
->buf_size
;
1798 DWORD_PTR ofs1
, ofs2
;
1799 DWORD_PTR boundary
= (DWORD_PTR
)buf
->data
;
1802 TRACE("(%p)->(%p, %u, %p, %u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1804 EnterCriticalSection(This
->crst
);
1805 setALContext(This
->ctx
);
1807 This
->buffer
->locked
= 0;
1808 hr
= DSERR_INVALIDPARAM
;
1810 /* Make sure offset is between boundary and boundary + bufsize */
1811 ofs1
= (DWORD_PTR
)ptr1
;
1812 ofs2
= (DWORD_PTR
)ptr2
;
1815 if(ofs2
&& ofs2
!= boundary
)
1819 if(bufsize
-ofs1
< len1
|| len2
> ofs1
)
1828 if(This
->ExtAL
->BufferDataStatic
)
1831 if(This
->ExtAL
->BufferSubSamplesSOFT
)
1833 WAVEFORMATEX
*format
= &buf
->format
.Format
;
1835 ptr1
= (BYTE
*)ptr1
- (ofs1
%format
->nBlockAlign
);
1836 ofs1
/= format
->nBlockAlign
;
1837 len1
/= format
->nBlockAlign
;
1839 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs1
, len1
,
1840 buf
->in_chans
, buf
->in_type
, ptr1
);
1841 ptr2
= (BYTE
*)ptr2
- (ofs2
%format
->nBlockAlign
);
1842 ofs2
/= format
->nBlockAlign
;
1843 len2
/= format
->nBlockAlign
;
1845 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs2
, len2
,
1846 buf
->in_chans
, buf
->in_type
, ptr2
);
1849 else if(This
->ExtAL
->BufferSubData
)
1851 WAVEFORMATEX
*format
= &buf
->format
.Format
;
1853 len1
-= len1
%format
->nBlockAlign
;
1855 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr1
,
1857 len2
-= len2
%format
->nBlockAlign
;
1859 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr2
,
1865 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1866 buf
->data
, buf
->buf_size
,
1867 buf
->format
.Format
.nSamplesPerSec
);
1873 WARN("Invalid parameters (0x%lx,%u) (%p,%u,%p,%u)\n", boundary
, bufsize
, ptr1
, len1
, ptr2
, len2
);
1875 LeaveCriticalSection(This
->crst
);
1879 static HRESULT WINAPI
DS8Buffer_Restore(IDirectSoundBuffer8
*iface
)
1881 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1884 TRACE("(%p)->()\n", iface
);
1886 EnterCriticalSection(This
->crst
);
1887 if(This
->primary
->parent
->prio_level
< DSSCL_WRITEPRIMARY
||
1888 iface
== This
->primary
->write_emu
)
1890 This
->bufferlost
= 0;
1894 hr
= DSERR_BUFFERLOST
;
1895 LeaveCriticalSection(This
->crst
);
1900 static HRESULT WINAPI
DS8Buffer_SetFX(IDirectSoundBuffer8
*iface
, DWORD fxcount
, DSEFFECTDESC
*desc
, DWORD
*rescodes
)
1902 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1905 TRACE("(%p)->(%u, %p, %p)\n", This
, fxcount
, desc
, rescodes
);
1907 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFX
))
1909 WARN("FX control not set\n");
1910 return DSERR_CONTROLUNAVAIL
;
1915 if(desc
|| rescodes
)
1917 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1918 return DSERR_INVALIDPARAM
;
1921 /* No effects; we can handle that */
1925 if(!desc
|| !rescodes
)
1927 WARN("NULL desc and/or result pointer specified.\n");
1928 return DSERR_INVALIDPARAM
;
1931 /* We don't (currently) handle DSound effects */
1932 for(i
= 0;i
< fxcount
;++i
)
1934 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc
[i
].guidDSFXClass
));
1935 rescodes
[i
] = DSFXR_FAILED
;
1938 return DSERR_INVALIDPARAM
;
1941 static HRESULT WINAPI
DS8Buffer_AcquireResources(IDirectSoundBuffer8
*iface
, DWORD flags
, DWORD fxcount
, DWORD
*rescodes
)
1943 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1945 TRACE("(%p)->(%u, %u, %p)\n", This
, flags
, fxcount
, rescodes
);
1947 /* effects aren't supported at the moment.. */
1948 if(fxcount
!= 0 || rescodes
)
1950 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1951 return DSERR_INVALIDPARAM
;
1954 EnterCriticalSection(This
->crst
);
1955 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1957 This
->buffer
->dsbflags
&= ~(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
);
1958 if((flags
&DSBPLAY_LOCSOFTWARE
))
1959 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1961 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1963 LeaveCriticalSection(This
->crst
);
1968 static HRESULT WINAPI
DS8Buffer_GetObjectInPath(IDirectSoundBuffer8
*iface
, REFGUID guid
, DWORD idx
, REFGUID rguidiface
, void **ppv
)
1970 FIXME("(%p)->(%s, %u, %s, %p) : stub!\n", iface
, debugstr_guid(guid
), idx
, debugstr_guid(rguidiface
), ppv
);
1974 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
=
1976 DS8Buffer_QueryInterface
,
1980 DS8Buffer_GetCurrentPosition
,
1981 DS8Buffer_GetFormat
,
1982 DS8Buffer_GetVolume
,
1984 DS8Buffer_GetFrequency
,
1985 DS8Buffer_GetStatus
,
1986 DS8Buffer_Initialize
,
1989 DS8Buffer_SetCurrentPosition
,
1990 DS8Buffer_SetFormat
,
1991 DS8Buffer_SetVolume
,
1993 DS8Buffer_SetFrequency
,
1998 DS8Buffer_AcquireResources
,
1999 DS8Buffer_GetObjectInPath
2003 static HRESULT WINAPI
DS8Buffer3D_QueryInterface(IDirectSound3DBuffer
*iface
, REFIID riid
, void **ppv
)
2005 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2006 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2009 static ULONG WINAPI
DS8Buffer3D_AddRef(IDirectSound3DBuffer
*iface
)
2011 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2014 InterlockedIncrement(&This
->all_ref
);
2015 ret
= InterlockedIncrement(&This
->ds3d_ref
);
2016 TRACE("new refcount %d\n", ret
);
2021 static ULONG WINAPI
DS8Buffer3D_Release(IDirectSound3DBuffer
*iface
)
2023 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2026 ret
= InterlockedDecrement(&This
->ds3d_ref
);
2027 TRACE("new refcount %d\n", ret
);
2028 if(InterlockedDecrement(&This
->all_ref
) == 0)
2029 DS8Buffer_Destroy(This
);
2034 static HRESULT WINAPI
DS8Buffer3D_GetAllParameters(IDirectSound3DBuffer
*iface
, DS3DBUFFER
*ds3dbuffer
)
2036 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2040 TRACE("%p\n", This
);
2042 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2044 WARN("Invalid parameters %p %u\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2045 return DSERR_INVALIDPARAM
;
2047 ds3dbuf
.dwSize
= sizeof(ds3dbuf
);
2049 EnterCriticalSection(This
->crst
);
2050 setALContext(This
->ctx
);
2052 hr
= IDirectSound3DBuffer_GetPosition(iface
, &ds3dbuf
.vPosition
);
2054 hr
= IDirectSound3DBuffer_GetVelocity(iface
, &ds3dbuf
.vVelocity
);
2056 hr
= IDirectSound3DBuffer_GetConeAngles(iface
, &ds3dbuf
.dwInsideConeAngle
, &ds3dbuf
.dwOutsideConeAngle
);
2058 hr
= IDirectSound3DBuffer_GetConeOrientation(iface
, &ds3dbuf
.vConeOrientation
);
2060 hr
= IDirectSound3DBuffer_GetConeOutsideVolume(iface
, &ds3dbuf
.lConeOutsideVolume
);
2062 hr
= IDirectSound3DBuffer_GetMinDistance(iface
, &ds3dbuf
.flMinDistance
);
2064 hr
= IDirectSound3DBuffer_GetMaxDistance(iface
, &ds3dbuf
.flMaxDistance
);
2066 hr
= IDirectSound3DBuffer_GetMode(iface
, &ds3dbuf
.dwMode
);
2068 memcpy(ds3dbuffer
, &ds3dbuf
, sizeof(ds3dbuf
));
2071 LeaveCriticalSection(This
->crst
);
2076 static HRESULT WINAPI
DS8Buffer3D_GetConeAngles(IDirectSound3DBuffer
*iface
, DWORD
*pdwInsideConeAngle
, DWORD
*pdwOutsideConeAngle
)
2078 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2079 ALint inangle
, outangle
;
2081 TRACE("(%p)->(%p, %p)\n", This
, pdwInsideConeAngle
, pdwOutsideConeAngle
);
2082 if(!pdwInsideConeAngle
|| !pdwOutsideConeAngle
)
2084 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle
, pdwOutsideConeAngle
);
2085 return DSERR_INVALIDPARAM
;
2088 EnterCriticalSection(This
->crst
);
2089 setALContext(This
->ctx
);
2091 alGetSourcei(This
->source
, AL_CONE_INNER_ANGLE
, &inangle
);
2092 alGetSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, &outangle
);
2094 *pdwInsideConeAngle
= inangle
;
2095 *pdwOutsideConeAngle
= outangle
;
2098 LeaveCriticalSection(This
->crst
);
2103 static HRESULT WINAPI
DS8Buffer3D_GetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVECTOR
*orient
)
2105 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2108 TRACE("(%p)->(%p)\n", This
, orient
);
2111 WARN("Invalid pointer\n");
2112 return DSERR_INVALIDPARAM
;
2115 EnterCriticalSection(This
->crst
);
2116 setALContext(This
->ctx
);
2118 alGetSourcefv(This
->source
, AL_DIRECTION
, dir
);
2122 orient
->z
= -dir
[2];
2125 LeaveCriticalSection(This
->crst
);
2130 static HRESULT WINAPI
DS8Buffer3D_GetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG
*vol
)
2132 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2135 TRACE("(%p)->(%p)\n", This
, vol
);
2138 WARN("Invalid pointer\n");
2139 return DSERR_INVALIDPARAM
;
2142 EnterCriticalSection(This
->crst
);
2143 setALContext(This
->ctx
);
2145 alGetSourcef(This
->source
, AL_CONE_OUTER_GAIN
, &gain
);
2147 *vol
= gain_to_mB(gain
);
2148 *vol
= max(*vol
, DSBVOLUME_MIN
);
2149 *vol
= min(*vol
, DSBVOLUME_MAX
);
2152 LeaveCriticalSection(This
->crst
);
2156 static HRESULT WINAPI
DS8Buffer3D_GetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*maxdist
)
2158 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2161 TRACE("(%p)->(%p)\n", This
, maxdist
);
2164 WARN("Invalid pointer\n");
2165 return DSERR_INVALIDPARAM
;
2168 EnterCriticalSection(This
->crst
);
2169 setALContext(This
->ctx
);
2171 alGetSourcef(This
->source
, AL_MAX_DISTANCE
, &dist
);
2176 LeaveCriticalSection(This
->crst
);
2181 static HRESULT WINAPI
DS8Buffer3D_GetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*mindist
)
2183 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2186 TRACE("(%p)->(%p)\n", This
, mindist
);
2189 WARN("Invalid pointer\n");
2190 return DSERR_INVALIDPARAM
;
2193 EnterCriticalSection(This
->crst
);
2194 setALContext(This
->ctx
);
2196 alGetSourcef(This
->source
, AL_REFERENCE_DISTANCE
, &dist
);
2201 LeaveCriticalSection(This
->crst
);
2206 static HRESULT WINAPI
DS8Buffer3D_GetMode(IDirectSound3DBuffer
*iface
, DWORD
*mode
)
2208 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2210 TRACE("(%p)->(%p)\n", This
, mode
);
2213 WARN("Invalid pointer\n");
2214 return DSERR_INVALIDPARAM
;
2217 EnterCriticalSection(This
->crst
);
2218 *mode
= This
->ds3dmode
;
2219 LeaveCriticalSection(This
->crst
);
2224 static HRESULT WINAPI
DS8Buffer3D_GetPosition(IDirectSound3DBuffer
*iface
, D3DVECTOR
*pos
)
2226 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2229 TRACE("(%p)->(%p)\n", This
, pos
);
2232 WARN("Invalid pointer\n");
2233 return DSERR_INVALIDPARAM
;
2236 EnterCriticalSection(This
->crst
);
2237 setALContext(This
->ctx
);
2239 alGetSourcefv(This
->source
, AL_POSITION
, alpos
);
2246 LeaveCriticalSection(This
->crst
);
2251 static HRESULT WINAPI
DS8Buffer3D_GetVelocity(IDirectSound3DBuffer
*iface
, D3DVECTOR
*vel
)
2253 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2256 TRACE("(%p)->(%p)\n", This
, vel
);
2259 WARN("Invalid pointer\n");
2260 return DSERR_INVALIDPARAM
;
2263 EnterCriticalSection(This
->crst
);
2264 setALContext(This
->ctx
);
2266 alGetSourcefv(This
->source
, AL_VELOCITY
, alvel
);
2273 LeaveCriticalSection(This
->crst
);
2278 static HRESULT WINAPI
DS8Buffer3D_SetAllParameters(IDirectSound3DBuffer
*iface
, const DS3DBUFFER
*ds3dbuffer
, DWORD apply
)
2280 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2281 TRACE("(%p)->(%p, %u)\n", This
, ds3dbuffer
, apply
);
2283 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2285 WARN("Invalid DS3DBUFFER (%p, %u)\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2286 return DSERR_INVALIDPARAM
;
2289 if(ds3dbuffer
->dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2290 ds3dbuffer
->dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2292 WARN("Invalid cone angles (%u, %u)\n", ds3dbuffer
->dwInsideConeAngle
,
2293 ds3dbuffer
->dwOutsideConeAngle
);
2294 return DSERR_INVALIDPARAM
;
2297 if(ds3dbuffer
->lConeOutsideVolume
> DSBVOLUME_MAX
||
2298 ds3dbuffer
->lConeOutsideVolume
< DSBVOLUME_MIN
)
2300 WARN("Invalid cone outside volume (%d)\n", ds3dbuffer
->lConeOutsideVolume
);
2301 return DSERR_INVALIDPARAM
;
2304 if(ds3dbuffer
->flMaxDistance
< 0.0f
)
2306 WARN("Invalid max distance (%f)\n", ds3dbuffer
->flMaxDistance
);
2307 return DSERR_INVALIDPARAM
;
2310 if(ds3dbuffer
->flMinDistance
< 0.0f
)
2312 WARN("Invalid min distance (%f)\n", ds3dbuffer
->flMinDistance
);
2313 return DSERR_INVALIDPARAM
;
2316 if(ds3dbuffer
->dwMode
!= DS3DMODE_NORMAL
&&
2317 ds3dbuffer
->dwMode
!= DS3DMODE_HEADRELATIVE
&&
2318 ds3dbuffer
->dwMode
!= DS3DMODE_DISABLE
)
2320 WARN("Invalid mode (%u)\n", ds3dbuffer
->dwMode
);
2321 return DSERR_INVALIDPARAM
;
2324 EnterCriticalSection(This
->crst
);
2325 setALContext(This
->ctx
);
2326 IDirectSound3DBuffer_SetPosition(iface
, ds3dbuffer
->vPosition
.x
, ds3dbuffer
->vPosition
.y
, ds3dbuffer
->vPosition
.z
, apply
);
2327 IDirectSound3DBuffer_SetVelocity(iface
, ds3dbuffer
->vVelocity
.x
, ds3dbuffer
->vVelocity
.y
, ds3dbuffer
->vVelocity
.z
, apply
);
2328 IDirectSound3DBuffer_SetConeAngles(iface
, ds3dbuffer
->dwInsideConeAngle
, ds3dbuffer
->dwOutsideConeAngle
, apply
);
2329 IDirectSound3DBuffer_SetConeOrientation(iface
, ds3dbuffer
->vConeOrientation
.x
, ds3dbuffer
->vConeOrientation
.y
, ds3dbuffer
->vConeOrientation
.z
, apply
);
2330 IDirectSound3DBuffer_SetConeOutsideVolume(iface
, ds3dbuffer
->lConeOutsideVolume
, apply
);
2331 IDirectSound3DBuffer_SetMinDistance(iface
, ds3dbuffer
->flMinDistance
, apply
);
2332 IDirectSound3DBuffer_SetMaxDistance(iface
, ds3dbuffer
->flMaxDistance
, apply
);
2333 IDirectSound3DBuffer_SetMode(iface
, ds3dbuffer
->dwMode
, apply
);
2335 LeaveCriticalSection(This
->crst
);
2340 static HRESULT WINAPI
DS8Buffer3D_SetConeAngles(IDirectSound3DBuffer
*iface
, DWORD dwInsideConeAngle
, DWORD dwOutsideConeAngle
, DWORD apply
)
2342 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2344 TRACE("(%p)->(%u, %u, %u)\n", This
, dwInsideConeAngle
, dwOutsideConeAngle
, apply
);
2345 if(dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2346 dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2348 WARN("Invalid cone angles (%u, %u)\n", dwInsideConeAngle
, dwOutsideConeAngle
);
2349 return DSERR_INVALIDPARAM
;
2352 EnterCriticalSection(This
->crst
);
2353 if(apply
== DS3D_DEFERRED
)
2355 This
->ds3dbuffer
.dwInsideConeAngle
= dwInsideConeAngle
;
2356 This
->ds3dbuffer
.dwOutsideConeAngle
= dwOutsideConeAngle
;
2357 This
->dirty
.bit
.cone_angles
= 1;
2361 setALContext(This
->ctx
);
2362 alSourcei(This
->source
, AL_CONE_INNER_ANGLE
, dwInsideConeAngle
);
2363 alSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, dwOutsideConeAngle
);
2367 LeaveCriticalSection(This
->crst
);
2372 static HRESULT WINAPI
DS8Buffer3D_SetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2374 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2376 TRACE("(%p)->(%f, %f, %f, %u)\n", This
, x
, y
, z
, apply
);
2378 EnterCriticalSection(This
->crst
);
2379 if(apply
== DS3D_DEFERRED
)
2381 This
->ds3dbuffer
.vConeOrientation
.x
= x
;
2382 This
->ds3dbuffer
.vConeOrientation
.y
= y
;
2383 This
->ds3dbuffer
.vConeOrientation
.z
= z
;
2384 This
->dirty
.bit
.cone_orient
= 1;
2388 setALContext(This
->ctx
);
2389 alSource3f(This
->source
, AL_DIRECTION
, x
, y
, -z
);
2393 LeaveCriticalSection(This
->crst
);
2398 static HRESULT WINAPI
DS8Buffer3D_SetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG vol
, DWORD apply
)
2400 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2402 TRACE("(%p)->(%u, %u)\n", This
, vol
, apply
);
2403 if(vol
< DSBVOLUME_MIN
|| vol
> DSBVOLUME_MAX
)
2405 WARN("Invalid volume (%u)\n", vol
);
2406 return DSERR_INVALIDPARAM
;
2409 EnterCriticalSection(This
->crst
);
2410 if(apply
== DS3D_DEFERRED
)
2412 This
->ds3dbuffer
.lConeOutsideVolume
= vol
;
2413 This
->dirty
.bit
.cone_outsidevolume
= 1;
2417 setALContext(This
->ctx
);
2418 alSourcef(This
->source
, AL_CONE_OUTER_GAIN
, mB_to_gain(vol
));
2422 LeaveCriticalSection(This
->crst
);
2427 static HRESULT WINAPI
DS8Buffer3D_SetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE maxdist
, DWORD apply
)
2429 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2431 TRACE("(%p)->(%f, %u)\n", This
, maxdist
, apply
);
2434 WARN("Invalid max distance (%f)\n", maxdist
);
2435 return DSERR_INVALIDPARAM
;
2438 EnterCriticalSection(This
->crst
);
2439 if(apply
== DS3D_DEFERRED
)
2441 This
->ds3dbuffer
.flMaxDistance
= maxdist
;
2442 This
->dirty
.bit
.max_distance
= 1;
2446 setALContext(This
->ctx
);
2447 alSourcef(This
->source
, AL_MAX_DISTANCE
, maxdist
);
2451 LeaveCriticalSection(This
->crst
);
2456 static HRESULT WINAPI
DS8Buffer3D_SetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE mindist
, DWORD apply
)
2458 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2460 TRACE("(%p)->(%f, %u)\n", This
, mindist
, apply
);
2463 WARN("Invalid min distance (%f)\n", mindist
);
2464 return DSERR_INVALIDPARAM
;
2467 EnterCriticalSection(This
->crst
);
2468 if(apply
== DS3D_DEFERRED
)
2470 This
->ds3dbuffer
.flMinDistance
= mindist
;
2471 This
->dirty
.bit
.min_distance
= 1;
2475 setALContext(This
->ctx
);
2476 alSourcef(This
->source
, AL_REFERENCE_DISTANCE
, mindist
);
2480 LeaveCriticalSection(This
->crst
);
2485 static HRESULT WINAPI
DS8Buffer3D_SetMode(IDirectSound3DBuffer
*iface
, DWORD mode
, DWORD apply
)
2487 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2489 TRACE("(%p)->(%u, %u)\n", This
, mode
, apply
);
2490 if(mode
!= DS3DMODE_NORMAL
&& mode
!= DS3DMODE_HEADRELATIVE
&&
2491 mode
!= DS3DMODE_DISABLE
)
2493 WARN("Invalid mode (%u)\n", mode
);
2494 return DSERR_INVALIDPARAM
;
2497 EnterCriticalSection(This
->crst
);
2498 if(apply
== DS3D_DEFERRED
)
2500 This
->ds3dbuffer
.dwMode
= mode
;
2501 This
->dirty
.bit
.mode
= 1;
2505 setALContext(This
->ctx
);
2506 alSourcei(This
->source
, AL_SOURCE_RELATIVE
,
2507 (mode
!= DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
2508 alSourcef(This
->source
, AL_ROLLOFF_FACTOR
,
2509 (mode
== DS3DMODE_DISABLE
) ? 0.0f
: This
->primary
->rollofffactor
);
2510 This
->ds3dmode
= mode
;
2514 LeaveCriticalSection(This
->crst
);
2519 static HRESULT WINAPI
DS8Buffer3D_SetPosition(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2521 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2523 TRACE("(%p)->(%f, %f, %f, %u)\n", This
, x
, y
, z
, apply
);
2525 EnterCriticalSection(This
->crst
);
2526 if(apply
== DS3D_DEFERRED
)
2528 This
->ds3dbuffer
.vPosition
.x
= x
;
2529 This
->ds3dbuffer
.vPosition
.y
= y
;
2530 This
->ds3dbuffer
.vPosition
.z
= z
;
2531 This
->dirty
.bit
.pos
= 1;
2535 setALContext(This
->ctx
);
2536 alSource3f(This
->source
, AL_POSITION
, x
, y
, -z
);
2540 LeaveCriticalSection(This
->crst
);
2545 static HRESULT WINAPI
DS8Buffer3D_SetVelocity(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2547 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2549 TRACE("(%p)->(%f, %f, %f, %u)\n", This
, x
, y
, z
, apply
);
2551 EnterCriticalSection(This
->crst
);
2552 if(apply
== DS3D_DEFERRED
)
2554 This
->ds3dbuffer
.vVelocity
.x
= x
;
2555 This
->ds3dbuffer
.vVelocity
.y
= y
;
2556 This
->ds3dbuffer
.vVelocity
.z
= z
;
2557 This
->dirty
.bit
.vel
= 1;
2561 setALContext(This
->ctx
);
2562 alSource3f(This
->source
, AL_VELOCITY
, x
, y
, -z
);
2566 LeaveCriticalSection(This
->crst
);
2571 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
=
2573 DS8Buffer3D_QueryInterface
,
2575 DS8Buffer3D_Release
,
2576 DS8Buffer3D_GetAllParameters
,
2577 DS8Buffer3D_GetConeAngles
,
2578 DS8Buffer3D_GetConeOrientation
,
2579 DS8Buffer3D_GetConeOutsideVolume
,
2580 DS8Buffer3D_GetMaxDistance
,
2581 DS8Buffer3D_GetMinDistance
,
2582 DS8Buffer3D_GetMode
,
2583 DS8Buffer3D_GetPosition
,
2584 DS8Buffer3D_GetVelocity
,
2585 DS8Buffer3D_SetAllParameters
,
2586 DS8Buffer3D_SetConeAngles
,
2587 DS8Buffer3D_SetConeOrientation
,
2588 DS8Buffer3D_SetConeOutsideVolume
,
2589 DS8Buffer3D_SetMaxDistance
,
2590 DS8Buffer3D_SetMinDistance
,
2591 DS8Buffer3D_SetMode
,
2592 DS8Buffer3D_SetPosition
,
2593 DS8Buffer3D_SetVelocity
2597 static HRESULT WINAPI
DS8BufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
2599 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2600 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2603 static ULONG WINAPI
DS8BufferNot_AddRef(IDirectSoundNotify
*iface
)
2605 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2608 InterlockedIncrement(&This
->all_ref
);
2609 ret
= InterlockedIncrement(&This
->not_ref
);
2610 TRACE("new refcount %d\n", ret
);
2615 static ULONG WINAPI
DS8BufferNot_Release(IDirectSoundNotify
*iface
)
2617 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2620 ret
= InterlockedDecrement(&This
->not_ref
);
2621 TRACE("new refcount %d\n", ret
);
2622 if(InterlockedDecrement(&This
->all_ref
) == 0)
2623 DS8Buffer_Destroy(This
);
2628 static HRESULT WINAPI
DS8BufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
2630 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2631 DSBPOSITIONNOTIFY
*nots
;
2635 EnterCriticalSection(This
->crst
);
2636 hr
= DSERR_INVALIDPARAM
;
2637 if(count
&& !notifications
)
2640 hr
= IDirectSoundBuffer8_GetStatus(&This
->IDirectSoundBuffer8_iface
, &state
);
2644 hr
= DSERR_INVALIDCALL
;
2645 if((state
&DSBSTATUS_PLAYING
))
2650 HeapFree(GetProcessHeap(), 0, This
->notify
);
2659 hr
= DSERR_INVALIDPARAM
;
2660 for(i
= 0;i
< count
;++i
)
2662 if(notifications
[i
].dwOffset
>= This
->buffer
->buf_size
&&
2663 notifications
[i
].dwOffset
!= (DWORD
)DSBPN_OFFSETSTOP
)
2668 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
2671 memcpy(nots
, notifications
, count
*sizeof(*nots
));
2673 HeapFree(GetProcessHeap(), 0, This
->notify
);
2674 This
->notify
= nots
;
2675 This
->nnotify
= count
;
2681 LeaveCriticalSection(This
->crst
);
2685 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
=
2687 DS8BufferNot_QueryInterface
,
2688 DS8BufferNot_AddRef
,
2689 DS8BufferNot_Release
,
2690 DS8BufferNot_SetNotificationPositions
2694 static HRESULT WINAPI
DS8BufferProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
2696 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2697 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2700 static ULONG WINAPI
DS8BufferProp_AddRef(IKsPropertySet
*iface
)
2702 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2705 InterlockedIncrement(&This
->all_ref
);
2706 ret
= InterlockedIncrement(&This
->prop_ref
);
2707 TRACE("new refcount %d\n", ret
);
2712 static ULONG WINAPI
DS8BufferProp_Release(IKsPropertySet
*iface
)
2714 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2717 ret
= InterlockedDecrement(&This
->prop_ref
);
2718 TRACE("new refcount %d\n", ret
);
2719 if(InterlockedDecrement(&This
->all_ref
) == 0)
2720 DS8Buffer_Destroy(This
);
2725 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2726 handled through secondary buffers. */
2727 static HRESULT WINAPI
DS8BufferProp_Get(IKsPropertySet
*iface
,
2728 REFGUID guidPropSet
, ULONG dwPropID
,
2729 LPVOID pInstanceData
, ULONG cbInstanceData
,
2730 LPVOID pPropData
, ULONG cbPropData
,
2733 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2734 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2736 TRACE("(%p)->(%s, %u, %p, %u, %p, %u, %p)\n", iface
, debugstr_guid(guidPropSet
),
2737 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
2744 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2750 /* Not a known buffer/source property. Pass it to the listener */
2751 hr
= IKsPropertySet_Get(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2752 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
,
2759 static HRESULT WINAPI
DS8BufferProp_Set(IKsPropertySet
*iface
,
2760 REFGUID guidPropSet
, ULONG dwPropID
,
2761 LPVOID pInstanceData
, ULONG cbInstanceData
,
2762 LPVOID pPropData
, ULONG cbPropData
)
2764 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2765 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2767 TRACE("(%p)->(%s, %u, %p, %u, %p, %u)\n", iface
, debugstr_guid(guidPropSet
),
2768 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
2771 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2777 /* Not a known buffer/source property. Pass it to the listener */
2778 hr
= IKsPropertySet_Set(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2779 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
,
2786 static HRESULT WINAPI
DS8BufferProp_QuerySupport(IKsPropertySet
*iface
,
2787 REFGUID guidPropSet
, ULONG dwPropID
,
2788 PULONG pTypeSupport
)
2790 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2791 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2793 TRACE("(%p)->(%s, %u, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
2800 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2806 /* Not a known buffer/source property. Pass it to the listener */
2807 hr
= IKsPropertySet_QuerySupport(&This
->primary
->IKsPropertySet_iface
,
2808 guidPropSet
, dwPropID
, pTypeSupport
);
2814 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
=
2816 DS8BufferProp_QueryInterface
,
2817 DS8BufferProp_AddRef
,
2818 DS8BufferProp_Release
,
2821 DS8BufferProp_QuerySupport