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";
199 else if(format
->wBitsPerSample
== 16)
201 switch(format
->nChannels
)
203 case 1: return "AL_FORMAT_MONO16";
204 case 2: return "AL_FORMAT_STEREO16";
205 case 4: return "AL_FORMAT_QUAD16";
206 case 6: return "AL_FORMAT_51CHN16";
207 case 7: return "AL_FORMAT_61CHN16";
208 case 8: return "AL_FORMAT_71CHN16";
212 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
213 format
->wBitsPerSample
, format
->nChannels
);
216 static ALenum
get_fmt_PCM(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
218 out
->Format
= *format
;
219 out
->Format
.cbSize
= 0;
221 if(format
->wBitsPerSample
== 8)
223 *in_type
= AL_UNSIGNED_BYTE
;
224 switch(format
->nChannels
)
226 case 1: *in_chans
= AL_MONO
;
228 case 2: *in_chans
= AL_STEREO
;
230 case 4: *in_chans
= AL_QUAD
;
232 case 6: *in_chans
= AL_5POINT1
;
234 case 7: *in_chans
= AL_6POINT1
;
236 case 8: *in_chans
= AL_7POINT1
;
240 else if(format
->wBitsPerSample
== 16)
243 switch(format
->nChannels
)
245 case 1: *in_chans
= AL_MONO
;
247 case 2: *in_chans
= AL_STEREO
;
249 case 4: *in_chans
= AL_QUAD
;
251 case 6: *in_chans
= AL_5POINT1
;
252 return AL_5POINT1_16
;
253 case 7: *in_chans
= AL_6POINT1
;
254 return AL_6POINT1_16
;
255 case 8: *in_chans
= AL_7POINT1
;
256 return AL_7POINT1_16
;
259 #if 0 /* Will cause incorrect byte offsets */
260 else if(format
->wBitsPerSample
== 24)
263 switch(format
->nChannels
)
265 case 1: *in_chans
= AL_MONO
;
267 case 2: *in_chans
= AL_STEREO
;
269 case 4: *in_chans
= AL_QUAD
;
271 case 6: *in_chans
= AL_5POINT1
;
272 return AL_5POINT1_32F
;
273 case 7: *in_chans
= AL_6POINT1
;
274 return AL_6POINT1_32F
;
275 case 8: *in_chans
= AL_7POINT1
;
276 return AL_7POINT1_32F
;
280 else if(format
->wBitsPerSample
== 32)
283 switch(format
->nChannels
)
285 case 1: *in_chans
= AL_MONO
;
287 case 2: *in_chans
= AL_STEREO
;
289 case 4: *in_chans
= AL_QUAD
;
291 case 6: *in_chans
= AL_5POINT1
;
292 return AL_5POINT1_32F
;
293 case 7: *in_chans
= AL_6POINT1
;
294 return AL_6POINT1_32F
;
295 case 8: *in_chans
= AL_7POINT1
;
296 return AL_7POINT1_32F
;
300 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
301 format
->wBitsPerSample
, format
->nChannels
);
305 static const char *get_fmtstr_FLOAT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
307 out
->Format
= *format
;
308 out
->Format
.cbSize
= 0;
310 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
311 !prim
->SupportedExt
[EXT_MCFORMATS
])
313 WARN("Multi-channel not available\n");
317 if(format
->wBitsPerSample
== 32 && prim
->SupportedExt
[EXT_FLOAT32
])
319 switch(format
->nChannels
)
321 case 1: return "AL_FORMAT_MONO_FLOAT32";
322 case 2: return "AL_FORMAT_STEREO_FLOAT32";
323 case 4: return "AL_FORMAT_QUAD32";
324 case 6: return "AL_FORMAT_51CHN32";
325 case 7: return "AL_FORMAT_61CHN32";
326 case 8: return "AL_FORMAT_71CHN32";
330 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
331 format
->wBitsPerSample
, format
->nChannels
);
334 static ALenum
get_fmt_FLOAT(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
336 out
->Format
= *format
;
337 out
->Format
.cbSize
= 0;
339 if(format
->wBitsPerSample
== 32)
342 switch(format
->nChannels
)
344 case 1: *in_chans
= AL_MONO
;
346 case 2: *in_chans
= AL_STEREO
;
348 case 4: *in_chans
= AL_QUAD
;
350 case 6: *in_chans
= AL_5POINT1
;
351 return AL_5POINT1_32F
;
352 case 7: *in_chans
= AL_6POINT1
;
353 return AL_6POINT1_32F
;
354 case 8: *in_chans
= AL_7POINT1
;
355 return AL_7POINT1_32F
;
358 #if 0 /* Will cause incorrect byte offsets */
359 else if(format
->wBitsPerSample
== 64)
361 *in_type
= AL_DOUBLE
;
362 switch(format
->nChannels
)
364 case 1: *in_chans
= AL_MONO
;
366 case 2: *in_chans
= AL_STEREO
;
368 case 4: *in_chans
= AL_QUAD
;
370 case 6: *in_chans
= AL_5POINT1
;
371 return AL_5POINT1_32F
;
372 case 7: *in_chans
= AL_6POINT1
;
373 return AL_6POINT1_32F
;
374 case 8: *in_chans
= AL_7POINT1
;
375 return AL_7POINT1_32F
;
380 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
381 format
->wBitsPerSample
, format
->nChannels
);
385 /* Speaker configs */
386 #define MONO SPEAKER_FRONT_CENTER
387 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
388 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
389 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
390 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
391 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
392 #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)
394 static const char *get_fmtstr_EXT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
396 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
397 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
399 if(!out
->Samples
.wValidBitsPerSample
)
400 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
401 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
403 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
407 if(out
->dwChannelMask
!= MONO
&& out
->dwChannelMask
!= STEREO
&&
408 !prim
->SupportedExt
[EXT_MCFORMATS
])
410 WARN("Multi-channel not available\n");
414 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
416 if(out
->Samples
.wValidBitsPerSample
== 8)
418 switch(out
->dwChannelMask
)
420 case MONO
: return "AL_FORMAT_MONO8";
421 case STEREO
: return "AL_FORMAT_STEREO8";
422 case REAR
: return "AL_FORMAT_REAR8";
423 case QUAD
: return "AL_FORMAT_QUAD8";
424 case X5DOT1
: return "AL_FORMAT_51CHN8";
425 case X6DOT1
: return "AL_FORMAT_61CHN8";
426 case X7DOT1
: return "AL_FORMAT_71CHN8";
429 else if(out
->Samples
.wValidBitsPerSample
== 16)
431 switch(out
->dwChannelMask
)
433 case MONO
: return "AL_FORMAT_MONO16";
434 case STEREO
: return "AL_FORMAT_STEREO16";
435 case REAR
: return "AL_FORMAT_REAR16";
436 case QUAD
: return "AL_FORMAT_QUAD16";
437 case X5DOT1
: return "AL_FORMAT_51CHN16";
438 case X6DOT1
: return "AL_FORMAT_61CHN16";
439 case X7DOT1
: return "AL_FORMAT_71CHN16";
443 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#x)\n",
444 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
447 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
448 prim
->SupportedExt
[EXT_FLOAT32
])
450 if(out
->Samples
.wValidBitsPerSample
== 32)
452 switch(out
->dwChannelMask
)
454 case MONO
: return "AL_FORMAT_MONO_FLOAT32";
455 case STEREO
: return "AL_FORMAT_STEREO_FLOAT32";
456 case REAR
: return "AL_FORMAT_REAR32";
457 case QUAD
: return "AL_FORMAT_QUAD32";
458 case X5DOT1
: return "AL_FORMAT_51CHN32";
459 case X6DOT1
: return "AL_FORMAT_61CHN32";
460 case X7DOT1
: return "AL_FORMAT_71CHN32";
465 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
469 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#x)\n",
470 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
473 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
474 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
477 static ALenum
get_fmt_EXT(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
479 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
480 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
482 if(!out
->Samples
.wValidBitsPerSample
)
483 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
484 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
486 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
490 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
492 if(out
->Samples
.wValidBitsPerSample
== 8)
494 *in_type
= AL_UNSIGNED_BYTE
;
495 switch(out
->dwChannelMask
)
497 case MONO
: *in_chans
= AL_MONO
;
499 case STEREO
: *in_chans
= AL_STEREO
;
501 case REAR
: *in_chans
= AL_REAR
;
503 case QUAD
: *in_chans
= AL_QUAD
;
505 case X5DOT1
: *in_chans
= AL_5POINT1
;
507 case X6DOT1
: *in_chans
= AL_6POINT1
;
509 case X7DOT1
: *in_chans
= AL_7POINT1
;
513 else if(out
->Samples
.wValidBitsPerSample
== 16)
516 switch(out
->dwChannelMask
)
518 case MONO
: *in_chans
= AL_MONO
;
520 case STEREO
: *in_chans
= AL_STEREO
;
522 case REAR
: *in_chans
= AL_REAR
;
524 case QUAD
: *in_chans
= AL_QUAD
;
526 case X5DOT1
: *in_chans
= AL_5POINT1
;
527 return AL_5POINT1_16
;
528 case X6DOT1
: *in_chans
= AL_6POINT1
;
529 return AL_6POINT1_16
;
530 case X7DOT1
: *in_chans
= AL_7POINT1
;
531 return AL_7POINT1_16
;
535 else if(out
->Samples
.wValidBitsPerSample
== 24)
538 switch(out
->dwChannelMask
)
540 case MONO
: *in_chans
= AL_MONO
;
542 case STEREO
: *in_chans
= AL_STEREO
;
544 case REAR
: *in_chans
= AL_REAR
;
546 case QUAD
: *in_chans
= AL_QUAD
;
548 case X5DOT1
: *in_chans
= AL_5POINT1
;
549 return AL_5POINT1_32F
;
550 case X6DOT1
: *in_chans
= AL_6POINT1
;
551 return AL_6POINT1_32F
;
552 case X7DOT1
: *in_chans
= AL_7POINT1
;
553 return AL_7POINT1_32F
;
557 else if(out
->Samples
.wValidBitsPerSample
== 32)
560 switch(out
->dwChannelMask
)
562 case MONO
: *in_chans
= AL_MONO
;
564 case STEREO
: *in_chans
= AL_STEREO
;
566 case REAR
: *in_chans
= AL_REAR
;
568 case QUAD
: *in_chans
= AL_QUAD
;
570 case X5DOT1
: *in_chans
= AL_5POINT1
;
571 return AL_5POINT1_32F
;
572 case X6DOT1
: *in_chans
= AL_6POINT1
;
573 return AL_6POINT1_32F
;
574 case X7DOT1
: *in_chans
= AL_7POINT1
;
575 return AL_7POINT1_32F
;
579 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#x)\n",
580 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
583 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
585 if(out
->Samples
.wValidBitsPerSample
== 32)
588 switch(out
->dwChannelMask
)
590 case MONO
: *in_chans
= AL_MONO
;
592 case STEREO
: *in_chans
= AL_STEREO
;
594 case REAR
: *in_chans
= AL_REAR
;
596 case QUAD
: *in_chans
= AL_QUAD
;
598 case X5DOT1
: *in_chans
= AL_5POINT1
;
599 return AL_5POINT1_32F
;
600 case X6DOT1
: *in_chans
= AL_6POINT1
;
601 return AL_6POINT1_32F
;
602 case X7DOT1
: *in_chans
= AL_7POINT1
;
603 return AL_7POINT1_32F
;
607 else if(out
->Samples
.wValidBitsPerSample
== 64)
609 *in_type
= AL_DOUBLE
;
610 switch(out
->dwChannelMask
)
612 case MONO
: *in_chans
= AL_MONO
;
614 case STEREO
: *in_chans
= AL_STEREO
;
616 case REAR
: *in_chans
= AL_REAR
;
618 case QUAD
: *in_chans
= AL_QUAD
;
620 case X5DOT1
: *in_chans
= AL_5POINT1
;
621 return AL_5POINT1_32F
;
622 case X6DOT1
: *in_chans
= AL_6POINT1
;
623 return AL_6POINT1_32F
;
624 case X7DOT1
: *in_chans
= AL_7POINT1
;
625 return AL_7POINT1_32F
;
631 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
635 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#x)\n",
636 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
639 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
640 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
644 static void DS8Data_Release(DS8Data
*This
);
645 static HRESULT
DS8Data_Create(DS8Data
**ppv
, const DSBUFFERDESC
*desc
, DS8Primary
*prim
)
647 HRESULT hr
= DSERR_INVALIDPARAM
;
648 const WAVEFORMATEX
*format
;
651 format
= desc
->lpwfxFormat
;
652 TRACE("Requested buffer format:\n"
653 " FormatTag = 0x%04x\n"
655 " SamplesPerSec = %u\n"
656 " AvgBytesPerSec = %u\n"
658 " BitsPerSample = %d\n",
659 format
->wFormatTag
, format
->nChannels
,
660 format
->nSamplesPerSec
, format
->nAvgBytesPerSec
,
661 format
->nBlockAlign
, format
->wBitsPerSample
);
663 if(format
->nBlockAlign
== 0)
665 WARN("Invalid BlockAlign specified\n");
666 return DSERR_INVALIDPARAM
;
669 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
670 * will need the EAX-RAM extension. Currently, we just tell the app it
671 * gets what it wanted. */
672 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
));
674 return E_OUTOFMEMORY
;
677 pBuffer
->dsbflags
= desc
->dwFlags
;
678 if((pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
)) == (DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
))
680 WARN("Hardware and software location requested\n");
683 if(!(pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCDEFER
)))
684 pBuffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
686 pBuffer
->buf_size
= desc
->dwBufferBytes
+ format
->nBlockAlign
- 1;
687 pBuffer
->buf_size
-= pBuffer
->buf_size
%format
->nBlockAlign
;
689 hr
= DSERR_BUFFERTOOSMALL
;
690 if(pBuffer
->buf_size
< DSBSIZE_MIN
)
693 hr
= DSERR_INVALIDPARAM
;
694 if(pBuffer
->buf_size
> DSBSIZE_MAX
)
697 pBuffer
->numsegs
= 1;
698 pBuffer
->segsize
= pBuffer
->buf_size
;
699 pBuffer
->lastsegsize
= pBuffer
->buf_size
;
701 if(!prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
705 if(!(pBuffer
->dsbflags
&DSBCAPS_STATIC
) && !prim
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] &&
706 !prim
->SupportedExt
[EXT_STATIC_BUFFER
])
708 ALCint refresh
= FAKE_REFRESH_COUNT
;
711 alcGetIntegerv(prim
->parent
->device
, ALC_REFRESH
, 1, &refresh
);
712 getALCError(prim
->parent
->device
);
714 newSize
= format
->nAvgBytesPerSec
/refresh
+ format
->nBlockAlign
- 1;
715 newSize
-= newSize
%format
->nBlockAlign
;
717 /* Make sure enough buffers are available */
718 if(newSize
> pBuffer
->buf_size
/(QBUFFERS
+2))
719 ERR("Buffer segments too large to stream (%u for %u)!\n",
720 newSize
, pBuffer
->buf_size
);
723 pBuffer
->numsegs
= pBuffer
->buf_size
/newSize
;
724 pBuffer
->segsize
= newSize
;
725 pBuffer
->lastsegsize
= pBuffer
->buf_size
- (newSize
*(pBuffer
->numsegs
-1));
726 TRACE("New streaming buffer (%u chunks, %u : %u sizes)\n",
727 pBuffer
->numsegs
, pBuffer
->segsize
, pBuffer
->lastsegsize
);
731 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
732 fmt_str
= get_fmtstr_PCM(prim
, format
, &pBuffer
->format
);
733 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
734 fmt_str
= get_fmtstr_FLOAT(prim
, format
, &pBuffer
->format
);
735 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
737 const WAVEFORMATEXTENSIBLE
*wfe
;
739 hr
= DSERR_CONTROLUNAVAIL
;
740 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
741 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
744 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
745 TRACE("Extensible values:\n"
747 " ChannelMask = 0x%x\n"
749 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
750 debugstr_guid(&wfe
->SubFormat
));
752 fmt_str
= get_fmtstr_EXT(prim
, format
, &pBuffer
->format
);
755 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
757 hr
= DSERR_INVALIDCALL
;
761 pBuffer
->buf_format
= alGetEnumValue(fmt_str
);
762 if(alGetError() != AL_NO_ERROR
|| pBuffer
->buf_format
== 0 ||
763 pBuffer
->buf_format
== -1)
765 WARN("Could not get OpenAL format from %s\n", fmt_str
);
771 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
772 pBuffer
->buf_format
= get_fmt_PCM(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
773 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
774 pBuffer
->buf_format
= get_fmt_FLOAT(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
775 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
777 const WAVEFORMATEXTENSIBLE
*wfe
;
779 hr
= DSERR_CONTROLUNAVAIL
;
780 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
781 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
784 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
785 TRACE("Extensible values:\n"
787 " ChannelMask = 0x%x\n"
789 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
790 debugstr_guid(&wfe
->SubFormat
));
792 pBuffer
->buf_format
= get_fmt_EXT(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
795 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
797 hr
= DSERR_INVALIDCALL
;
798 if(prim
->ExtAL
.IsBufferFormatSupportedSOFT(pBuffer
->buf_format
) == AL_FALSE
)
800 WARN("Unsupported OpenAL format: 0x%x\n", pBuffer
->buf_format
);
806 pBuffer
->buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
->buffers
)*pBuffer
->numsegs
);
807 pBuffer
->data
= HeapAlloc(GetProcessHeap(), 0, pBuffer
->buf_size
);
808 if(!pBuffer
->buffers
|| !pBuffer
->data
)
811 alGenBuffers(pBuffer
->numsegs
, pBuffer
->buffers
);
818 DS8Data_Release(pBuffer
);
822 static void DS8Data_AddRef(DS8Data
*data
)
824 InterlockedIncrement(&data
->ref
);
827 /* This function is always called with the device lock held */
828 static void DS8Data_Release(DS8Data
*This
)
830 if(InterlockedDecrement(&This
->ref
)) return;
832 TRACE("Deleting %p\n", This
);
833 if (This
->buffers
&& This
->buffers
[0])
835 alDeleteBuffers(This
->numsegs
, This
->buffers
);
838 HeapFree(GetProcessHeap(), 0, This
->buffers
);
839 HeapFree(GetProcessHeap(), 0, This
->data
);
840 HeapFree(GetProcessHeap(), 0, This
);
843 HRESULT
DS8Buffer_Create(DS8Buffer
**ppv
, DS8Primary
*prim
, IDirectSoundBuffer
*orig
)
849 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
850 if(!This
) return DSERR_OUTOFMEMORY
;
852 This
->IDirectSoundBuffer8_iface
.lpVtbl
= (IDirectSoundBuffer8Vtbl
*)&DS8Buffer_Vtbl
;
853 This
->IDirectSound3DBuffer_iface
.lpVtbl
= (IDirectSound3DBufferVtbl
*)&DS8Buffer3d_Vtbl
;
854 This
->IDirectSoundNotify_iface
.lpVtbl
= (IDirectSoundNotifyVtbl
*)&DS8BufferNot_Vtbl
;
855 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8BufferProp_Vtbl
;
857 This
->primary
= prim
;
858 This
->ctx
= prim
->ctx
;
859 This
->ExtAL
= &prim
->ExtAL
;
860 This
->crst
= &prim
->crst
;
861 This
->ref
= This
->all_ref
= 1;
865 DS8Buffer
*org
= impl_from_IDirectSoundBuffer(orig
);
866 hr
= DSERR_BUFFERLOST
;
869 DS8Data_AddRef(org
->buffer
);
870 This
->buffer
= org
->buffer
;
873 /* Append to buffer list */
874 if(prim
->nbuffers
== prim
->sizebuffers
)
878 hr
= DSERR_OUTOFMEMORY
;
879 bufs
= HeapReAlloc(GetProcessHeap(), 0, prim
->buffers
, sizeof(*bufs
)*(prim
->nbuffers
+1));
882 prim
->buffers
= bufs
;
885 prim
->buffers
[prim
->nbuffers
++] = This
;
887 /* Disable until initialized.. */
888 This
->ds3dmode
= DS3DMODE_DISABLE
;
894 DS8Buffer_Destroy(This
);
898 void DS8Buffer_Destroy(DS8Buffer
*This
)
900 DS8Primary
*prim
= This
->primary
;
903 TRACE("Destroying %p\n", This
);
905 EnterCriticalSection(&prim
->crst
);
906 /* Remove from list, if in list */
907 for(idx
= 0;idx
< prim
->nnotifies
;++idx
)
909 if(This
== prim
->notifies
[idx
])
911 prim
->notifies
[idx
] = prim
->notifies
[--prim
->nnotifies
];
915 for(idx
= 0;idx
< prim
->nbuffers
;++idx
)
917 if(prim
->buffers
[idx
] == This
)
919 prim
->buffers
[idx
] = prim
->buffers
[--prim
->nbuffers
];
924 setALContext(This
->ctx
);
929 alSourceStop(This
->source
);
930 alSourcei(This
->source
, AL_BUFFER
, 0);
933 sources
= prim
->sources
;
934 if(prim
->nsources
== prim
->sizesources
)
936 sources
= HeapReAlloc(GetProcessHeap(), 0, sources
, sizeof(*sources
)*(prim
->nsources
+1));
938 alDeleteSources(1, &This
->source
);
944 sources
[prim
->nsources
++] = This
->source
;
945 prim
->sources
= sources
;
949 LeaveCriticalSection(&prim
->crst
);
952 DS8Data_Release(This
->buffer
);
956 HeapFree(GetProcessHeap(), 0, This
->notify
);
957 HeapFree(GetProcessHeap(), 0, This
);
961 static HRESULT WINAPI
DS8Buffer_QueryInterface(IDirectSoundBuffer8
*iface
, REFIID riid
, void **ppv
)
963 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
965 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
968 if(IsEqualIID(riid
, &IID_IUnknown
) ||
969 IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
970 *ppv
= &This
->IDirectSoundBuffer8_iface
;
971 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer8
))
973 if(This
->primary
->parent
->is_8
)
974 *ppv
= &This
->IDirectSoundBuffer8_iface
;
976 else if(IsEqualIID(riid
, &IID_IDirectSound3DBuffer
))
978 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
979 *ppv
= &This
->IDirectSound3DBuffer_iface
;
981 else if(IsEqualIID(riid
, &IID_IDirectSoundNotify
))
983 if((This
->buffer
->dsbflags
&DSBCAPS_CTRLPOSITIONNOTIFY
))
984 *ppv
= &This
->IDirectSoundNotify_iface
;
986 else if(IsEqualIID(riid
, &IID_IKsPropertySet
))
987 *ppv
= &This
->IKsPropertySet_iface
;
989 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
993 IUnknown_AddRef((IUnknown
*)*ppv
);
997 return E_NOINTERFACE
;
1000 static ULONG WINAPI
DS8Buffer_AddRef(IDirectSoundBuffer8
*iface
)
1002 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1005 InterlockedIncrement(&This
->all_ref
);
1006 ret
= InterlockedIncrement(&This
->ref
);
1007 TRACE("new refcount %d\n", ret
);
1012 static ULONG WINAPI
DS8Buffer_Release(IDirectSoundBuffer8
*iface
)
1014 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1017 ret
= InterlockedDecrement(&This
->ref
);
1018 TRACE("new refcount %d\n", ret
);
1019 if(InterlockedDecrement(&This
->all_ref
) == 0)
1020 DS8Buffer_Destroy(This
);
1025 static HRESULT WINAPI
DS8Buffer_GetCaps(IDirectSoundBuffer8
*iface
, DSBCAPS
*caps
)
1027 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1029 TRACE("(%p)->(%p)\n", iface
, caps
);
1031 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
1033 WARN("Invalid DSBCAPS (%p, %u)\n", caps
, (caps
? caps
->dwSize
: 0));
1034 return DSERR_INVALIDPARAM
;
1037 caps
->dwFlags
= This
->buffer
->dsbflags
;
1038 caps
->dwBufferBytes
= This
->buffer
->buf_size
;
1039 caps
->dwUnlockTransferRate
= 4096;
1040 caps
->dwPlayCpuOverhead
= 0;
1044 static HRESULT WINAPI
DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD
*playpos
, DWORD
*curpos
)
1046 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1047 WAVEFORMATEX
*format
= &This
->buffer
->format
.Format
;
1048 UINT writecursor
, pos
;
1050 TRACE("(%p)->(%p, %p)\n", iface
, playpos
, curpos
);
1052 EnterCriticalSection(This
->crst
);
1053 setALContext(This
->ctx
);
1055 if(This
->buffer
->numsegs
> 1)
1057 ALint queued
= QBUFFERS
;
1058 alGetSourcei(This
->source
, AL_BUFFERS_QUEUED
, &queued
);
1061 pos
= (This
->curidx
+This
->buffer
->numsegs
-queued
)%This
->buffer
->numsegs
;
1062 pos
*= This
->buffer
->segsize
;
1063 writecursor
= This
->curidx
* This
->buffer
->segsize
;
1065 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] ||
1066 This
->primary
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
1068 ALint rwpos
[2] = { 0, 0 };
1070 alGetSourceiv(This
->source
, AL_BYTE_RW_OFFSETS_SOFT
, rwpos
);
1074 writecursor
= rwpos
[1];
1081 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
1082 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
1086 if(status
== AL_PLAYING
)
1088 writecursor
= format
->nSamplesPerSec
/ 100;
1089 writecursor
*= format
->nBlockAlign
;
1093 writecursor
= (writecursor
+ pos
) % This
->buffer
->buf_size
;
1095 TRACE("%p Play pos = %u, write pos = %u\n", This
, pos
, writecursor
);
1096 if(pos
>= This
->buffer
->buf_size
)
1098 ERR("playpos >= buf_size\n");
1099 pos
%= This
->buffer
->buf_size
;
1101 if(writecursor
>= This
->buffer
->buf_size
)
1103 ERR("writepos >= buf_size\n");
1104 writecursor
%= This
->buffer
->buf_size
;
1107 if(playpos
) *playpos
= pos
;
1108 if(curpos
) *curpos
= writecursor
;
1111 LeaveCriticalSection(This
->crst
);
1116 static HRESULT WINAPI
DS8Buffer_GetFormat(IDirectSoundBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
1118 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1122 TRACE("(%p)->(%p, %u, %p)\n", iface
, wfx
, allocated
, written
);
1124 if(!wfx
&& !written
)
1126 WARN("Cannot report format or format size\n");
1127 return DSERR_INVALIDPARAM
;
1130 size
= sizeof(This
->buffer
->format
.Format
) + This
->buffer
->format
.Format
.cbSize
;
1133 if(allocated
< size
)
1134 hr
= DSERR_INVALIDPARAM
;
1136 memcpy(wfx
, &This
->buffer
->format
.Format
, size
);
1144 static HRESULT WINAPI
DS8Buffer_GetVolume(IDirectSoundBuffer8
*iface
, LONG
*vol
)
1146 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1149 TRACE("(%p)->(%p)\n", iface
, vol
);
1153 WARN("Invalid pointer\n");
1154 return DSERR_INVALIDPARAM
;
1157 hr
= DSERR_CONTROLUNAVAIL
;
1158 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1159 WARN("Volume control not set\n");
1162 ALfloat gain
= 1.0f
;
1164 setALContext(This
->ctx
);
1165 alGetSourcef(This
->source
, AL_GAIN
, &gain
);
1169 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
1176 static HRESULT WINAPI
DS8Buffer_GetPan(IDirectSoundBuffer8
*iface
, LONG
*pan
)
1178 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1181 TRACE("(%p)->(%p)\n", iface
, pan
);
1185 WARN("Invalid pointer\n");
1186 return DSERR_INVALIDPARAM
;
1189 hr
= DSERR_CONTROLUNAVAIL
;
1190 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1191 WARN("Panning control not set\n");
1196 setALContext(This
->ctx
);
1197 alGetSourcefv(This
->source
, AL_POSITION
, pos
);
1201 *pan
= clampI(((pos
[0]+1.0) * (DSBPAN_RIGHT
-DSBPAN_LEFT
) / 2.0 + 0.5) + DSBPAN_LEFT
, DSBPAN_LEFT
, DSBPAN_RIGHT
);
1208 static HRESULT WINAPI
DS8Buffer_GetFrequency(IDirectSoundBuffer8
*iface
, DWORD
*freq
)
1210 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1213 TRACE("(%p)->(%p)\n", iface
, freq
);
1217 WARN("Invalid pointer\n");
1218 return DSERR_INVALIDPARAM
;
1221 hr
= DSERR_CONTROLUNAVAIL
;
1222 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1223 WARN("Frequency control not set\n");
1226 ALfloat pitch
= 1.0f
;
1228 setALContext(This
->ctx
);
1229 alGetSourcefv(This
->source
, AL_PITCH
, &pitch
);
1233 *freq
= (DWORD
)(This
->buffer
->format
.Format
.nSamplesPerSec
* pitch
);
1240 static HRESULT WINAPI
DS8Buffer_GetStatus(IDirectSoundBuffer8
*iface
, DWORD
*status
)
1242 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1243 ALint state
, looping
;
1245 TRACE("(%p)->(%p)\n", iface
, status
);
1249 WARN("Invalid pointer\n");
1250 return DSERR_INVALIDPARAM
;
1253 EnterCriticalSection(This
->crst
);
1255 setALContext(This
->ctx
);
1256 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1257 looping
= This
->islooping
;
1258 if(This
->buffer
->numsegs
== 1)
1259 alGetSourcei(This
->source
, AL_LOOPING
, &looping
);
1260 else if(state
!= AL_PLAYING
)
1261 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1265 LeaveCriticalSection(This
->crst
);
1268 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1270 if((This
->buffer
->dsbflags
&DSBCAPS_LOCSOFTWARE
))
1271 *status
|= DSBSTATUS_LOCSOFTWARE
;
1272 else if((This
->buffer
->dsbflags
&DSBCAPS_LOCHARDWARE
))
1273 *status
|= DSBSTATUS_LOCHARDWARE
;
1275 if(state
== AL_PLAYING
)
1276 *status
|= DSBSTATUS_PLAYING
| (looping
? DSBSTATUS_LOOPING
: 0);
1281 static HRESULT WINAPI
DS8Buffer_Initialize(IDirectSoundBuffer8
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
1283 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1284 DS3DBUFFER
*ds3dbuffer
;
1287 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
1289 EnterCriticalSection(This
->crst
);
1290 setALContext(This
->ctx
);
1292 hr
= DSERR_ALREADYINITIALIZED
;
1298 hr
= DSERR_INVALIDPARAM
;
1301 WARN("Missing DSound buffer description\n");
1304 if(!desc
->lpwfxFormat
)
1306 WARN("Missing buffer format (%p)\n", This
);
1309 if((desc
->dwFlags
&DSBCAPS_CTRL3D
) && desc
->lpwfxFormat
->nChannels
!= 1)
1311 if(This
->primary
->parent
->is_8
)
1313 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
1315 WARN("Can't create multi-channel 3D buffers\n");
1318 ERR("Multi-channel 3D sounds are not spatialized\n");
1321 hr
= DS8Data_Create(&This
->buffer
, desc
, This
->primary
);
1326 DS8Data
*buf
= This
->buffer
;
1328 if(buf
->format
.Format
.wBitsPerSample
== 8)
1329 memset(buf
->data
, 0x80, buf
->buf_size
);
1331 memset(buf
->data
, 0x00, buf
->buf_size
);
1333 if(This
->primary
->SupportedExt
[EXT_STATIC_BUFFER
])
1334 This
->ExtAL
->BufferDataStatic(buf
->buffers
[0], buf
->buf_format
,
1335 buf
->data
, buf
->buf_size
,
1336 buf
->format
.Format
.nSamplesPerSec
);
1337 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
1338 This
->ExtAL
->BufferSamplesSOFT(buf
->buffers
[0],
1339 buf
->format
.Format
.nSamplesPerSec
, buf
->buf_format
,
1340 buf
->buf_size
/buf
->format
.Format
.nBlockAlign
,
1341 buf
->in_chans
, buf
->in_type
, buf
->data
);
1342 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SUB_DATA
])
1343 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1344 buf
->data
, buf
->buf_size
,
1345 buf
->format
.Format
.nSamplesPerSec
);
1351 if(This
->primary
->nsources
)
1353 This
->source
= This
->primary
->sources
[--This
->primary
->nsources
];
1354 alSourcef(This
->source
, AL_GAIN
, 1.0f
);
1355 alSourcef(This
->source
, AL_PITCH
, 1.0f
);
1360 alGenSources(1, &This
->source
);
1361 if(alGetError() != AL_NO_ERROR
)
1365 ds3dbuffer
= &This
->ds3dbuffer
;
1366 ds3dbuffer
->dwSize
= sizeof(*ds3dbuffer
);
1367 ds3dbuffer
->vPosition
.x
= 0.0;
1368 ds3dbuffer
->vPosition
.y
= 0.0;
1369 ds3dbuffer
->vPosition
.z
= 0.0;
1370 ds3dbuffer
->vVelocity
.x
= 0.0;
1371 ds3dbuffer
->vVelocity
.y
= 0.0;
1372 ds3dbuffer
->vVelocity
.z
= 0.0;
1373 ds3dbuffer
->dwInsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1374 ds3dbuffer
->dwOutsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1375 ds3dbuffer
->vConeOrientation
.x
= 0.0;
1376 ds3dbuffer
->vConeOrientation
.y
= 0.0;
1377 ds3dbuffer
->vConeOrientation
.z
= 1.0;
1378 ds3dbuffer
->lConeOutsideVolume
= DS3D_DEFAULTCONEOUTSIDEVOLUME
;
1379 ds3dbuffer
->flMinDistance
= DS3D_DEFAULTMINDISTANCE
;
1380 ds3dbuffer
->flMaxDistance
= DS3D_DEFAULTMAXDISTANCE
;
1381 ds3dbuffer
->dwMode
= DS3DMODE_NORMAL
;
1383 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
1385 if(This
->primary
->auxslot
!= 0)
1387 alSource3i(This
->source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1391 hr
= IDirectSound3DBuffer_SetAllParameters(&This
->IDirectSound3DBuffer_iface
, ds3dbuffer
, DS3D_IMMEDIATE
);
1394 ERR("SetAllParameters failed\n");
1400 ALuint source
= This
->source
;
1402 if(This
->primary
->auxslot
!= 0)
1404 /* Simple hack to make reverb affect non-3D sounds too */
1405 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1406 /*alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);*/
1409 /* Non-3D sources aren't distance attenuated */
1410 This
->ds3dmode
= DS3DMODE_DISABLE
;
1411 alSource3f(source
, AL_POSITION
, 0.0f
, 1.0f
, 0.0f
);
1412 alSource3f(source
, AL_VELOCITY
, 0.0f
, 0.0f
, 0.0f
);
1413 alSource3f(source
, AL_DIRECTION
, 0.0f
, 0.0f
, 0.0f
);
1414 alSourcef(source
, AL_CONE_OUTER_GAIN
, 1.0f
);
1415 alSourcef(source
, AL_REFERENCE_DISTANCE
, 1.0f
);
1416 alSourcef(source
, AL_MAX_DISTANCE
, 1000.0f
);
1417 alSourcef(source
, AL_ROLLOFF_FACTOR
, 0.0f
);
1418 alSourcei(source
, AL_CONE_INNER_ANGLE
, 360);
1419 alSourcei(source
, AL_CONE_OUTER_ANGLE
, 360);
1420 alSourcei(source
, AL_SOURCE_RELATIVE
, AL_TRUE
);
1427 LeaveCriticalSection(This
->crst
);
1432 static HRESULT WINAPI
DS8Buffer_Lock(IDirectSoundBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1434 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1437 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, 0x%x)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1441 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
1442 return DSERR_INVALIDPARAM
;
1447 if(ptr2
) *ptr2
= NULL
;
1450 if((flags
&DSBLOCK_FROMWRITECURSOR
))
1451 DS8Buffer_GetCurrentPosition(iface
, NULL
, &ofs
);
1452 else if(ofs
>= This
->buffer
->buf_size
)
1454 WARN("Invalid ofs %u\n", ofs
);
1455 return DSERR_INVALIDPARAM
;
1457 if((flags
&DSBLOCK_ENTIREBUFFER
))
1458 bytes
= This
->buffer
->buf_size
;
1459 else if(bytes
> This
->buffer
->buf_size
)
1461 WARN("Invalid size %u\n", bytes
);
1462 return DSERR_INVALIDPARAM
;
1465 if(InterlockedExchange(&This
->buffer
->locked
, TRUE
) == TRUE
)
1467 WARN("Already locked\n");
1468 return DSERR_INVALIDPARAM
;
1471 *ptr1
= This
->buffer
->data
+ ofs
;
1472 if(ofs
+bytes
>= This
->buffer
->buf_size
)
1474 *len1
= This
->buffer
->buf_size
- ofs
;
1475 remain
= bytes
- *len1
;
1483 if(ptr2
&& len2
&& remain
)
1485 *ptr2
= This
->buffer
->data
;
1492 static HRESULT WINAPI
DS8Buffer_Play(IDirectSoundBuffer8
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1494 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1495 ALint type
, state
= AL_STOPPED
;
1499 TRACE("%p\n", This
);
1501 EnterCriticalSection(This
->crst
);
1502 setALContext(This
->ctx
);
1504 hr
= DSERR_BUFFERLOST
;
1505 if(This
->bufferlost
)
1507 WARN("Buffer %p lost\n", This
);
1511 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1513 if(!(This
->buffer
->dsbflags
&(DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCSOFTWARE
)))
1515 if(flags
& DSBPLAY_LOCSOFTWARE
)
1516 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1518 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1523 ERR("Invalid priority set for non-deferred buffer %p, %u!\n", This
->buffer
, prio
);
1524 hr
= DSERR_INVALIDPARAM
;
1528 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1529 if(This
->buffer
->numsegs
> 1)
1531 This
->islooping
= !!(flags
&DSBPLAY_LOOPING
);
1532 if(state
!= AL_PLAYING
&& This
->isplaying
)
1537 alGetSourcei(This
->source
, AL_SOURCE_TYPE
, &type
);
1538 alSourcei(This
->source
, AL_LOOPING
, (flags
&DSBPLAY_LOOPING
) ? AL_TRUE
: AL_FALSE
);
1543 if(state
== AL_PLAYING
)
1546 /* alSourceQueueBuffers will implicitly set type to streaming */
1547 if(This
->buffer
->numsegs
== 1)
1549 if(type
!= AL_STATIC
)
1550 alSourcei(This
->source
, AL_BUFFER
, This
->buffer
->buffers
[0]);
1551 alSourcePlay(This
->source
);
1553 if(alGetError() != AL_NO_ERROR
)
1555 ERR("Couldn't start source\n");
1556 This
->curidx
= (This
->buffer
->numsegs
-1+This
->curidx
)%This
->buffer
->numsegs
;
1557 alSourcei(This
->source
, AL_BUFFER
, 0);
1562 This
->isplaying
= TRUE
;
1566 DS8Buffer_addnotify(This
);
1567 DS8Buffer_starttimer(This
->primary
);
1569 else if(This
->buffer
->numsegs
> 1)
1570 DS8Buffer_starttimer(This
->primary
);
1574 LeaveCriticalSection(This
->crst
);
1578 static HRESULT WINAPI
DS8Buffer_SetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD pos
)
1580 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1582 TRACE("(%p)->(%u)\n", iface
, (UINT
)pos
);
1584 if(pos
>= This
->buffer
->buf_size
)
1585 return DSERR_INVALIDPARAM
;
1587 EnterCriticalSection(This
->crst
);
1589 if(This
->buffer
->numsegs
> 1)
1591 DS8Data
*buf
= This
->buffer
;
1592 This
->curidx
= pos
/buf
->segsize
;
1593 if(This
->curidx
>= buf
->numsegs
)
1594 This
->curidx
= buf
->numsegs
- 1;
1597 setALContext(This
->ctx
);
1598 /* Perform a flush, so the next timer update will restart at the
1599 * proper position */
1600 alSourceStop(This
->source
);
1607 setALContext(This
->ctx
);
1608 alSourcei(This
->source
, AL_BYTE_OFFSET
, pos
);
1611 This
->lastpos
= pos
;
1613 LeaveCriticalSection(This
->crst
);
1617 static HRESULT WINAPI
DS8Buffer_SetFormat(IDirectSoundBuffer8
*iface
, const WAVEFORMATEX
*wfx
)
1619 /* This call only works on primary buffers */
1620 WARN("(%p)->(%p)\n", iface
, wfx
);
1621 return DSERR_INVALIDCALL
;
1624 static HRESULT WINAPI
DS8Buffer_SetVolume(IDirectSoundBuffer8
*iface
, LONG vol
)
1626 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1629 TRACE("(%p)->(%d)\n", iface
, vol
);
1631 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
1633 WARN("Invalid volume (%d)\n", vol
);
1634 return DSERR_INVALIDPARAM
;
1637 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1638 hr
= DSERR_CONTROLUNAVAIL
;
1641 ALfloat fvol
= mB_to_gain(vol
);
1642 setALContext(This
->ctx
);
1643 alSourcef(This
->source
, AL_GAIN
, fvol
);
1650 static HRESULT WINAPI
DS8Buffer_SetPan(IDirectSoundBuffer8
*iface
, LONG pan
)
1652 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1655 TRACE("(%p)->(%d)\n", iface
, pan
);
1657 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
1659 WARN("invalid parameter: pan = %d\n", pan
);
1660 return DSERR_INVALIDPARAM
;
1663 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1664 hr
= DSERR_CONTROLUNAVAIL
;
1668 pos
[0] = (pan
-DSBPAN_LEFT
) * 2.0 / (ALfloat
)(DSBPAN_RIGHT
-DSBPAN_LEFT
) - 1.0;
1669 /* NOTE: Strict movement along the X plane can cause the sound to jump
1670 * between left and right sharply. Using a curved path helps smooth it
1672 pos
[1] = sqrt(1.0 - pos
[0]*pos
[0]);
1675 setALContext(This
->ctx
);
1676 alSourcefv(This
->source
, AL_POSITION
, pos
);
1680 if(pan
!= 0 && This
->buffer
->format
.Format
.nChannels
> 1)
1681 FIXME("Panning for multi-channel buffers is not supported\n");
1687 static HRESULT WINAPI
DS8Buffer_SetFrequency(IDirectSoundBuffer8
*iface
, DWORD freq
)
1689 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1692 TRACE("(%p)->(%u)\n", iface
, freq
);
1694 if(freq
< DSBFREQUENCY_MIN
|| freq
> DSBFREQUENCY_MAX
)
1696 WARN("invalid parameter: freq = %d\n", freq
);
1697 return DSERR_INVALIDPARAM
;
1700 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1701 hr
= DSERR_CONTROLUNAVAIL
;
1704 ALfloat pitch
= 1.0f
;
1705 if(freq
!= DSBFREQUENCY_ORIGINAL
)
1706 pitch
= freq
/ (ALfloat
)This
->buffer
->format
.Format
.nSamplesPerSec
;
1708 setALContext(This
->ctx
);
1709 alSourcef(This
->source
, AL_PITCH
, pitch
);
1717 static HRESULT WINAPI
DS8Buffer_Stop(IDirectSoundBuffer8
*iface
)
1719 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1722 TRACE("(%p)->()\n", iface
);
1724 EnterCriticalSection(This
->crst
);
1725 setALContext(This
->ctx
);
1727 alSourcePause(This
->source
);
1729 /* Mac OS X doesn't immediately report state change
1730 * if Play() is immediately called after Stop, this can be fatal,
1731 * the buffer would never be restarted
1735 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1736 if(state
!= AL_PLAYING
)
1741 This
->isplaying
= FALSE
;
1744 LeaveCriticalSection(This
->crst
);
1749 static HRESULT WINAPI
DS8Buffer_Unlock(IDirectSoundBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1751 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1752 DS8Data
*buf
= This
->buffer
;
1753 DWORD bufsize
= buf
->buf_size
;
1754 DWORD_PTR ofs1
, ofs2
;
1755 DWORD_PTR boundary
= (DWORD_PTR
)buf
->data
;
1758 TRACE("(%p)->(%p, %u, %p, %u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1760 if(InterlockedExchange(&This
->buffer
->locked
, FALSE
) == FALSE
)
1762 WARN("Not locked\n");
1763 return DSERR_INVALIDPARAM
;
1766 hr
= DSERR_INVALIDPARAM
;
1767 /* Make sure offset is between boundary and boundary + bufsize */
1768 ofs1
= (DWORD_PTR
)ptr1
;
1769 ofs2
= (DWORD_PTR
)ptr2
;
1772 if(ofs2
&& ofs2
!= boundary
)
1776 if(bufsize
-ofs1
< len1
|| len2
> ofs1
)
1784 if(This
->primary
->SupportedExt
[EXT_STATIC_BUFFER
])
1787 setALContext(This
->ctx
);
1788 if(This
->primary
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
1790 const WAVEFORMATEX
*format
= &buf
->format
.Format
;
1792 ptr1
= (BYTE
*)ptr1
- (ofs1
%format
->nBlockAlign
);
1793 ofs1
/= format
->nBlockAlign
;
1794 len1
/= format
->nBlockAlign
;
1796 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs1
, len1
,
1797 buf
->in_chans
, buf
->in_type
, ptr1
);
1798 ptr2
= (BYTE
*)ptr2
- (ofs2
%format
->nBlockAlign
);
1799 ofs2
/= format
->nBlockAlign
;
1800 len2
/= format
->nBlockAlign
;
1802 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs2
, len2
,
1803 buf
->in_chans
, buf
->in_type
, ptr2
);
1806 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SUB_DATA
])
1808 const WAVEFORMATEX
*format
= &buf
->format
.Format
;
1810 len1
-= len1
%format
->nBlockAlign
;
1812 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr1
,
1814 len2
-= len2
%format
->nBlockAlign
;
1816 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr2
,
1822 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1823 buf
->data
, buf
->buf_size
,
1824 buf
->format
.Format
.nSamplesPerSec
);
1831 WARN("Invalid parameters (0x%lx,%u) (%p,%u,%p,%u)\n", boundary
, bufsize
, ptr1
, len1
, ptr2
, len2
);
1835 static HRESULT WINAPI
DS8Buffer_Restore(IDirectSoundBuffer8
*iface
)
1837 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1840 TRACE("(%p)->()\n", iface
);
1842 EnterCriticalSection(This
->crst
);
1843 if(This
->primary
->parent
->prio_level
< DSSCL_WRITEPRIMARY
||
1844 iface
== This
->primary
->write_emu
)
1846 This
->bufferlost
= 0;
1850 hr
= DSERR_BUFFERLOST
;
1851 LeaveCriticalSection(This
->crst
);
1856 static HRESULT WINAPI
DS8Buffer_SetFX(IDirectSoundBuffer8
*iface
, DWORD fxcount
, DSEFFECTDESC
*desc
, DWORD
*rescodes
)
1858 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1861 TRACE("(%p)->(%u, %p, %p)\n", This
, fxcount
, desc
, rescodes
);
1863 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFX
))
1865 WARN("FX control not set\n");
1866 return DSERR_CONTROLUNAVAIL
;
1871 if(desc
|| rescodes
)
1873 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1874 return DSERR_INVALIDPARAM
;
1877 /* No effects; we can handle that */
1881 if(!desc
|| !rescodes
)
1883 WARN("NULL desc and/or result pointer specified.\n");
1884 return DSERR_INVALIDPARAM
;
1887 /* We don't (currently) handle DSound effects */
1888 for(i
= 0;i
< fxcount
;++i
)
1890 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc
[i
].guidDSFXClass
));
1891 rescodes
[i
] = DSFXR_FAILED
;
1894 return DS_INCOMPLETE
;
1897 static HRESULT WINAPI
DS8Buffer_AcquireResources(IDirectSoundBuffer8
*iface
, DWORD flags
, DWORD fxcount
, DWORD
*rescodes
)
1899 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1901 TRACE("(%p)->(%u, %u, %p)\n", This
, flags
, fxcount
, rescodes
);
1903 /* effects aren't supported at the moment.. */
1904 if(fxcount
!= 0 || rescodes
)
1906 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1907 return DSERR_INVALIDPARAM
;
1910 EnterCriticalSection(This
->crst
);
1911 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1913 This
->buffer
->dsbflags
&= ~(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
);
1914 if((flags
&DSBPLAY_LOCSOFTWARE
))
1915 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1917 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1919 LeaveCriticalSection(This
->crst
);
1924 static HRESULT WINAPI
DS8Buffer_GetObjectInPath(IDirectSoundBuffer8
*iface
, REFGUID guid
, DWORD idx
, REFGUID rguidiface
, void **ppv
)
1926 FIXME("(%p)->(%s, %u, %s, %p) : stub!\n", iface
, debugstr_guid(guid
), idx
, debugstr_guid(rguidiface
), ppv
);
1930 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
=
1932 DS8Buffer_QueryInterface
,
1936 DS8Buffer_GetCurrentPosition
,
1937 DS8Buffer_GetFormat
,
1938 DS8Buffer_GetVolume
,
1940 DS8Buffer_GetFrequency
,
1941 DS8Buffer_GetStatus
,
1942 DS8Buffer_Initialize
,
1945 DS8Buffer_SetCurrentPosition
,
1946 DS8Buffer_SetFormat
,
1947 DS8Buffer_SetVolume
,
1949 DS8Buffer_SetFrequency
,
1954 DS8Buffer_AcquireResources
,
1955 DS8Buffer_GetObjectInPath
1959 static HRESULT WINAPI
DS8Buffer3D_QueryInterface(IDirectSound3DBuffer
*iface
, REFIID riid
, void **ppv
)
1961 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1962 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
1965 static ULONG WINAPI
DS8Buffer3D_AddRef(IDirectSound3DBuffer
*iface
)
1967 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1970 InterlockedIncrement(&This
->all_ref
);
1971 ret
= InterlockedIncrement(&This
->ds3d_ref
);
1972 TRACE("new refcount %d\n", ret
);
1977 static ULONG WINAPI
DS8Buffer3D_Release(IDirectSound3DBuffer
*iface
)
1979 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1982 ret
= InterlockedDecrement(&This
->ds3d_ref
);
1983 TRACE("new refcount %d\n", ret
);
1984 if(InterlockedDecrement(&This
->all_ref
) == 0)
1985 DS8Buffer_Destroy(This
);
1990 static HRESULT WINAPI
DS8Buffer3D_GetAllParameters(IDirectSound3DBuffer
*iface
, DS3DBUFFER
*ds3dbuffer
)
1992 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1996 TRACE("%p\n", This
);
1998 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2000 WARN("Invalid parameters %p %u\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2001 return DSERR_INVALIDPARAM
;
2003 ds3dbuf
.dwSize
= sizeof(ds3dbuf
);
2005 EnterCriticalSection(This
->crst
);
2006 setALContext(This
->ctx
);
2008 hr
= IDirectSound3DBuffer_GetPosition(iface
, &ds3dbuf
.vPosition
);
2010 hr
= IDirectSound3DBuffer_GetVelocity(iface
, &ds3dbuf
.vVelocity
);
2012 hr
= IDirectSound3DBuffer_GetConeAngles(iface
, &ds3dbuf
.dwInsideConeAngle
, &ds3dbuf
.dwOutsideConeAngle
);
2014 hr
= IDirectSound3DBuffer_GetConeOrientation(iface
, &ds3dbuf
.vConeOrientation
);
2016 hr
= IDirectSound3DBuffer_GetConeOutsideVolume(iface
, &ds3dbuf
.lConeOutsideVolume
);
2018 hr
= IDirectSound3DBuffer_GetMinDistance(iface
, &ds3dbuf
.flMinDistance
);
2020 hr
= IDirectSound3DBuffer_GetMaxDistance(iface
, &ds3dbuf
.flMaxDistance
);
2022 hr
= IDirectSound3DBuffer_GetMode(iface
, &ds3dbuf
.dwMode
);
2024 memcpy(ds3dbuffer
, &ds3dbuf
, sizeof(ds3dbuf
));
2027 LeaveCriticalSection(This
->crst
);
2032 static HRESULT WINAPI
DS8Buffer3D_GetConeAngles(IDirectSound3DBuffer
*iface
, DWORD
*pdwInsideConeAngle
, DWORD
*pdwOutsideConeAngle
)
2034 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2035 ALint inangle
, outangle
;
2037 TRACE("(%p)->(%p, %p)\n", This
, pdwInsideConeAngle
, pdwOutsideConeAngle
);
2038 if(!pdwInsideConeAngle
|| !pdwOutsideConeAngle
)
2040 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle
, pdwOutsideConeAngle
);
2041 return DSERR_INVALIDPARAM
;
2044 EnterCriticalSection(This
->crst
);
2045 setALContext(This
->ctx
);
2047 alGetSourcei(This
->source
, AL_CONE_INNER_ANGLE
, &inangle
);
2048 alGetSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, &outangle
);
2050 *pdwInsideConeAngle
= inangle
;
2051 *pdwOutsideConeAngle
= outangle
;
2054 LeaveCriticalSection(This
->crst
);
2059 static HRESULT WINAPI
DS8Buffer3D_GetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVECTOR
*orient
)
2061 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2064 TRACE("(%p)->(%p)\n", This
, orient
);
2067 WARN("Invalid pointer\n");
2068 return DSERR_INVALIDPARAM
;
2071 EnterCriticalSection(This
->crst
);
2072 setALContext(This
->ctx
);
2074 alGetSourcefv(This
->source
, AL_DIRECTION
, dir
);
2078 orient
->z
= -dir
[2];
2081 LeaveCriticalSection(This
->crst
);
2086 static HRESULT WINAPI
DS8Buffer3D_GetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG
*vol
)
2088 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2091 TRACE("(%p)->(%p)\n", This
, vol
);
2094 WARN("Invalid pointer\n");
2095 return DSERR_INVALIDPARAM
;
2098 EnterCriticalSection(This
->crst
);
2099 setALContext(This
->ctx
);
2101 alGetSourcef(This
->source
, AL_CONE_OUTER_GAIN
, &gain
);
2105 LeaveCriticalSection(This
->crst
);
2107 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
2111 static HRESULT WINAPI
DS8Buffer3D_GetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*maxdist
)
2113 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2116 TRACE("(%p)->(%p)\n", This
, maxdist
);
2119 WARN("Invalid pointer\n");
2120 return DSERR_INVALIDPARAM
;
2123 EnterCriticalSection(This
->crst
);
2124 setALContext(This
->ctx
);
2126 alGetSourcef(This
->source
, AL_MAX_DISTANCE
, &dist
);
2130 LeaveCriticalSection(This
->crst
);
2136 static HRESULT WINAPI
DS8Buffer3D_GetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*mindist
)
2138 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2141 TRACE("(%p)->(%p)\n", This
, mindist
);
2144 WARN("Invalid pointer\n");
2145 return DSERR_INVALIDPARAM
;
2148 EnterCriticalSection(This
->crst
);
2149 setALContext(This
->ctx
);
2151 alGetSourcef(This
->source
, AL_REFERENCE_DISTANCE
, &dist
);
2156 LeaveCriticalSection(This
->crst
);
2161 static HRESULT WINAPI
DS8Buffer3D_GetMode(IDirectSound3DBuffer
*iface
, DWORD
*mode
)
2163 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2165 TRACE("(%p)->(%p)\n", This
, mode
);
2168 WARN("Invalid pointer\n");
2169 return DSERR_INVALIDPARAM
;
2172 EnterCriticalSection(This
->crst
);
2173 *mode
= This
->ds3dmode
;
2174 LeaveCriticalSection(This
->crst
);
2179 static HRESULT WINAPI
DS8Buffer3D_GetPosition(IDirectSound3DBuffer
*iface
, D3DVECTOR
*pos
)
2181 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2184 TRACE("(%p)->(%p)\n", This
, pos
);
2187 WARN("Invalid pointer\n");
2188 return DSERR_INVALIDPARAM
;
2191 EnterCriticalSection(This
->crst
);
2192 setALContext(This
->ctx
);
2194 alGetSourcefv(This
->source
, AL_POSITION
, alpos
);
2201 LeaveCriticalSection(This
->crst
);
2206 static HRESULT WINAPI
DS8Buffer3D_GetVelocity(IDirectSound3DBuffer
*iface
, D3DVECTOR
*vel
)
2208 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2211 TRACE("(%p)->(%p)\n", This
, vel
);
2214 WARN("Invalid pointer\n");
2215 return DSERR_INVALIDPARAM
;
2218 EnterCriticalSection(This
->crst
);
2219 setALContext(This
->ctx
);
2221 alGetSourcefv(This
->source
, AL_VELOCITY
, alvel
);
2228 LeaveCriticalSection(This
->crst
);
2233 static HRESULT WINAPI
DS8Buffer3D_SetAllParameters(IDirectSound3DBuffer
*iface
, const DS3DBUFFER
*ds3dbuffer
, DWORD apply
)
2235 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2236 TRACE("(%p)->(%p, %u)\n", This
, ds3dbuffer
, apply
);
2238 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2240 WARN("Invalid DS3DBUFFER (%p, %u)\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2241 return DSERR_INVALIDPARAM
;
2244 if(ds3dbuffer
->dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2245 ds3dbuffer
->dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2247 WARN("Invalid cone angles (%u, %u)\n", ds3dbuffer
->dwInsideConeAngle
,
2248 ds3dbuffer
->dwOutsideConeAngle
);
2249 return DSERR_INVALIDPARAM
;
2252 if(ds3dbuffer
->lConeOutsideVolume
> DSBVOLUME_MAX
||
2253 ds3dbuffer
->lConeOutsideVolume
< DSBVOLUME_MIN
)
2255 WARN("Invalid cone outside volume (%d)\n", ds3dbuffer
->lConeOutsideVolume
);
2256 return DSERR_INVALIDPARAM
;
2259 if(ds3dbuffer
->flMaxDistance
< 0.0f
)
2261 WARN("Invalid max distance (%f)\n", ds3dbuffer
->flMaxDistance
);
2262 return DSERR_INVALIDPARAM
;
2265 if(ds3dbuffer
->flMinDistance
< 0.0f
)
2267 WARN("Invalid min distance (%f)\n", ds3dbuffer
->flMinDistance
);
2268 return DSERR_INVALIDPARAM
;
2271 if(ds3dbuffer
->dwMode
!= DS3DMODE_NORMAL
&&
2272 ds3dbuffer
->dwMode
!= DS3DMODE_HEADRELATIVE
&&
2273 ds3dbuffer
->dwMode
!= DS3DMODE_DISABLE
)
2275 WARN("Invalid mode (%u)\n", ds3dbuffer
->dwMode
);
2276 return DSERR_INVALIDPARAM
;
2279 EnterCriticalSection(This
->crst
);
2280 setALContext(This
->ctx
);
2281 IDirectSound3DBuffer_SetPosition(iface
, ds3dbuffer
->vPosition
.x
, ds3dbuffer
->vPosition
.y
, ds3dbuffer
->vPosition
.z
, apply
);
2282 IDirectSound3DBuffer_SetVelocity(iface
, ds3dbuffer
->vVelocity
.x
, ds3dbuffer
->vVelocity
.y
, ds3dbuffer
->vVelocity
.z
, apply
);
2283 IDirectSound3DBuffer_SetConeAngles(iface
, ds3dbuffer
->dwInsideConeAngle
, ds3dbuffer
->dwOutsideConeAngle
, apply
);
2284 IDirectSound3DBuffer_SetConeOrientation(iface
, ds3dbuffer
->vConeOrientation
.x
, ds3dbuffer
->vConeOrientation
.y
, ds3dbuffer
->vConeOrientation
.z
, apply
);
2285 IDirectSound3DBuffer_SetConeOutsideVolume(iface
, ds3dbuffer
->lConeOutsideVolume
, apply
);
2286 IDirectSound3DBuffer_SetMinDistance(iface
, ds3dbuffer
->flMinDistance
, apply
);
2287 IDirectSound3DBuffer_SetMaxDistance(iface
, ds3dbuffer
->flMaxDistance
, apply
);
2288 IDirectSound3DBuffer_SetMode(iface
, ds3dbuffer
->dwMode
, apply
);
2290 LeaveCriticalSection(This
->crst
);
2295 static HRESULT WINAPI
DS8Buffer3D_SetConeAngles(IDirectSound3DBuffer
*iface
, DWORD dwInsideConeAngle
, DWORD dwOutsideConeAngle
, DWORD apply
)
2297 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2299 TRACE("(%p)->(%u, %u, %u)\n", This
, dwInsideConeAngle
, dwOutsideConeAngle
, apply
);
2300 if(dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2301 dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2303 WARN("Invalid cone angles (%u, %u)\n", dwInsideConeAngle
, dwOutsideConeAngle
);
2304 return DSERR_INVALIDPARAM
;
2307 EnterCriticalSection(This
->crst
);
2308 if(apply
== DS3D_DEFERRED
)
2310 This
->ds3dbuffer
.dwInsideConeAngle
= dwInsideConeAngle
;
2311 This
->ds3dbuffer
.dwOutsideConeAngle
= dwOutsideConeAngle
;
2312 This
->dirty
.bit
.cone_angles
= 1;
2316 setALContext(This
->ctx
);
2317 alSourcei(This
->source
, AL_CONE_INNER_ANGLE
, dwInsideConeAngle
);
2318 alSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, dwOutsideConeAngle
);
2322 LeaveCriticalSection(This
->crst
);
2327 static HRESULT WINAPI
DS8Buffer3D_SetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2329 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2331 TRACE("(%p)->(%f, %f, %f, %u)\n", This
, x
, y
, z
, apply
);
2333 EnterCriticalSection(This
->crst
);
2334 if(apply
== DS3D_DEFERRED
)
2336 This
->ds3dbuffer
.vConeOrientation
.x
= x
;
2337 This
->ds3dbuffer
.vConeOrientation
.y
= y
;
2338 This
->ds3dbuffer
.vConeOrientation
.z
= z
;
2339 This
->dirty
.bit
.cone_orient
= 1;
2343 setALContext(This
->ctx
);
2344 alSource3f(This
->source
, AL_DIRECTION
, x
, y
, -z
);
2348 LeaveCriticalSection(This
->crst
);
2353 static HRESULT WINAPI
DS8Buffer3D_SetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG vol
, DWORD apply
)
2355 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2357 TRACE("(%p)->(%u, %u)\n", This
, vol
, apply
);
2358 if(vol
< DSBVOLUME_MIN
|| vol
> DSBVOLUME_MAX
)
2360 WARN("Invalid volume (%u)\n", vol
);
2361 return DSERR_INVALIDPARAM
;
2364 EnterCriticalSection(This
->crst
);
2365 if(apply
== DS3D_DEFERRED
)
2367 This
->ds3dbuffer
.lConeOutsideVolume
= vol
;
2368 This
->dirty
.bit
.cone_outsidevolume
= 1;
2372 setALContext(This
->ctx
);
2373 alSourcef(This
->source
, AL_CONE_OUTER_GAIN
, mB_to_gain(vol
));
2377 LeaveCriticalSection(This
->crst
);
2382 static HRESULT WINAPI
DS8Buffer3D_SetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE maxdist
, DWORD apply
)
2384 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2386 TRACE("(%p)->(%f, %u)\n", This
, maxdist
, apply
);
2389 WARN("Invalid max distance (%f)\n", maxdist
);
2390 return DSERR_INVALIDPARAM
;
2393 EnterCriticalSection(This
->crst
);
2394 if(apply
== DS3D_DEFERRED
)
2396 This
->ds3dbuffer
.flMaxDistance
= maxdist
;
2397 This
->dirty
.bit
.max_distance
= 1;
2401 setALContext(This
->ctx
);
2402 alSourcef(This
->source
, AL_MAX_DISTANCE
, maxdist
);
2406 LeaveCriticalSection(This
->crst
);
2411 static HRESULT WINAPI
DS8Buffer3D_SetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE mindist
, DWORD apply
)
2413 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2415 TRACE("(%p)->(%f, %u)\n", This
, mindist
, apply
);
2418 WARN("Invalid min distance (%f)\n", mindist
);
2419 return DSERR_INVALIDPARAM
;
2422 EnterCriticalSection(This
->crst
);
2423 if(apply
== DS3D_DEFERRED
)
2425 This
->ds3dbuffer
.flMinDistance
= mindist
;
2426 This
->dirty
.bit
.min_distance
= 1;
2430 setALContext(This
->ctx
);
2431 alSourcef(This
->source
, AL_REFERENCE_DISTANCE
, mindist
);
2435 LeaveCriticalSection(This
->crst
);
2440 static HRESULT WINAPI
DS8Buffer3D_SetMode(IDirectSound3DBuffer
*iface
, DWORD mode
, DWORD apply
)
2442 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2444 TRACE("(%p)->(%u, %u)\n", This
, mode
, apply
);
2445 if(mode
!= DS3DMODE_NORMAL
&& mode
!= DS3DMODE_HEADRELATIVE
&&
2446 mode
!= DS3DMODE_DISABLE
)
2448 WARN("Invalid mode (%u)\n", mode
);
2449 return DSERR_INVALIDPARAM
;
2452 EnterCriticalSection(This
->crst
);
2453 if(apply
== DS3D_DEFERRED
)
2455 This
->ds3dbuffer
.dwMode
= mode
;
2456 This
->dirty
.bit
.mode
= 1;
2460 setALContext(This
->ctx
);
2461 alSourcei(This
->source
, AL_SOURCE_RELATIVE
,
2462 (mode
!= DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
2463 alSourcef(This
->source
, AL_ROLLOFF_FACTOR
,
2464 (mode
== DS3DMODE_DISABLE
) ? 0.0f
: This
->primary
->rollofffactor
);
2465 This
->ds3dmode
= mode
;
2469 LeaveCriticalSection(This
->crst
);
2474 static HRESULT WINAPI
DS8Buffer3D_SetPosition(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2476 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2478 TRACE("(%p)->(%f, %f, %f, %u)\n", This
, x
, y
, z
, apply
);
2480 EnterCriticalSection(This
->crst
);
2481 if(apply
== DS3D_DEFERRED
)
2483 This
->ds3dbuffer
.vPosition
.x
= x
;
2484 This
->ds3dbuffer
.vPosition
.y
= y
;
2485 This
->ds3dbuffer
.vPosition
.z
= z
;
2486 This
->dirty
.bit
.pos
= 1;
2490 setALContext(This
->ctx
);
2491 alSource3f(This
->source
, AL_POSITION
, x
, y
, -z
);
2495 LeaveCriticalSection(This
->crst
);
2500 static HRESULT WINAPI
DS8Buffer3D_SetVelocity(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2502 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2504 TRACE("(%p)->(%f, %f, %f, %u)\n", This
, x
, y
, z
, apply
);
2506 EnterCriticalSection(This
->crst
);
2507 if(apply
== DS3D_DEFERRED
)
2509 This
->ds3dbuffer
.vVelocity
.x
= x
;
2510 This
->ds3dbuffer
.vVelocity
.y
= y
;
2511 This
->ds3dbuffer
.vVelocity
.z
= z
;
2512 This
->dirty
.bit
.vel
= 1;
2516 setALContext(This
->ctx
);
2517 alSource3f(This
->source
, AL_VELOCITY
, x
, y
, -z
);
2521 LeaveCriticalSection(This
->crst
);
2526 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
=
2528 DS8Buffer3D_QueryInterface
,
2530 DS8Buffer3D_Release
,
2531 DS8Buffer3D_GetAllParameters
,
2532 DS8Buffer3D_GetConeAngles
,
2533 DS8Buffer3D_GetConeOrientation
,
2534 DS8Buffer3D_GetConeOutsideVolume
,
2535 DS8Buffer3D_GetMaxDistance
,
2536 DS8Buffer3D_GetMinDistance
,
2537 DS8Buffer3D_GetMode
,
2538 DS8Buffer3D_GetPosition
,
2539 DS8Buffer3D_GetVelocity
,
2540 DS8Buffer3D_SetAllParameters
,
2541 DS8Buffer3D_SetConeAngles
,
2542 DS8Buffer3D_SetConeOrientation
,
2543 DS8Buffer3D_SetConeOutsideVolume
,
2544 DS8Buffer3D_SetMaxDistance
,
2545 DS8Buffer3D_SetMinDistance
,
2546 DS8Buffer3D_SetMode
,
2547 DS8Buffer3D_SetPosition
,
2548 DS8Buffer3D_SetVelocity
2552 static HRESULT WINAPI
DS8BufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
2554 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2555 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2558 static ULONG WINAPI
DS8BufferNot_AddRef(IDirectSoundNotify
*iface
)
2560 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2563 InterlockedIncrement(&This
->all_ref
);
2564 ret
= InterlockedIncrement(&This
->not_ref
);
2565 TRACE("new refcount %d\n", ret
);
2570 static ULONG WINAPI
DS8BufferNot_Release(IDirectSoundNotify
*iface
)
2572 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2575 ret
= InterlockedDecrement(&This
->not_ref
);
2576 TRACE("new refcount %d\n", ret
);
2577 if(InterlockedDecrement(&This
->all_ref
) == 0)
2578 DS8Buffer_Destroy(This
);
2583 static HRESULT WINAPI
DS8BufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
2585 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2586 DSBPOSITIONNOTIFY
*nots
;
2590 EnterCriticalSection(This
->crst
);
2591 hr
= DSERR_INVALIDPARAM
;
2592 if(count
&& !notifications
)
2595 hr
= IDirectSoundBuffer8_GetStatus(&This
->IDirectSoundBuffer8_iface
, &state
);
2599 hr
= DSERR_INVALIDCALL
;
2600 if((state
&DSBSTATUS_PLAYING
))
2605 HeapFree(GetProcessHeap(), 0, This
->notify
);
2614 hr
= DSERR_INVALIDPARAM
;
2615 for(i
= 0;i
< count
;++i
)
2617 if(notifications
[i
].dwOffset
>= This
->buffer
->buf_size
&&
2618 notifications
[i
].dwOffset
!= (DWORD
)DSBPN_OFFSETSTOP
)
2623 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
2626 memcpy(nots
, notifications
, count
*sizeof(*nots
));
2628 HeapFree(GetProcessHeap(), 0, This
->notify
);
2629 This
->notify
= nots
;
2630 This
->nnotify
= count
;
2636 LeaveCriticalSection(This
->crst
);
2640 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
=
2642 DS8BufferNot_QueryInterface
,
2643 DS8BufferNot_AddRef
,
2644 DS8BufferNot_Release
,
2645 DS8BufferNot_SetNotificationPositions
2649 static HRESULT WINAPI
DS8BufferProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
2651 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2652 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2655 static ULONG WINAPI
DS8BufferProp_AddRef(IKsPropertySet
*iface
)
2657 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2660 InterlockedIncrement(&This
->all_ref
);
2661 ret
= InterlockedIncrement(&This
->prop_ref
);
2662 TRACE("new refcount %d\n", ret
);
2667 static ULONG WINAPI
DS8BufferProp_Release(IKsPropertySet
*iface
)
2669 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2672 ret
= InterlockedDecrement(&This
->prop_ref
);
2673 TRACE("new refcount %d\n", ret
);
2674 if(InterlockedDecrement(&This
->all_ref
) == 0)
2675 DS8Buffer_Destroy(This
);
2680 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2681 handled through secondary buffers. */
2682 static HRESULT WINAPI
DS8BufferProp_Get(IKsPropertySet
*iface
,
2683 REFGUID guidPropSet
, ULONG dwPropID
,
2684 LPVOID pInstanceData
, ULONG cbInstanceData
,
2685 LPVOID pPropData
, ULONG cbPropData
,
2688 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2689 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2691 TRACE("(%p)->(%s, %u, %p, %u, %p, %u, %p)\n", iface
, debugstr_guid(guidPropSet
),
2692 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
2699 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2705 /* Not a known buffer/source property. Pass it to the listener */
2706 hr
= IKsPropertySet_Get(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2707 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
,
2714 static HRESULT WINAPI
DS8BufferProp_Set(IKsPropertySet
*iface
,
2715 REFGUID guidPropSet
, ULONG dwPropID
,
2716 LPVOID pInstanceData
, ULONG cbInstanceData
,
2717 LPVOID pPropData
, ULONG cbPropData
)
2719 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2720 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2722 TRACE("(%p)->(%s, %u, %p, %u, %p, %u)\n", iface
, debugstr_guid(guidPropSet
),
2723 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
2726 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2732 /* Not a known buffer/source property. Pass it to the listener */
2733 hr
= IKsPropertySet_Set(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2734 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
,
2741 static HRESULT WINAPI
DS8BufferProp_QuerySupport(IKsPropertySet
*iface
,
2742 REFGUID guidPropSet
, ULONG dwPropID
,
2743 PULONG pTypeSupport
)
2745 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2746 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2748 TRACE("(%p)->(%s, %u, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
2755 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2761 /* Not a known buffer/source property. Pass it to the listener */
2762 hr
= IKsPropertySet_QuerySupport(&This
->primary
->IKsPropertySet_iface
,
2763 guidPropSet
, dwPropID
, pTypeSupport
);
2769 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
=
2771 DS8BufferProp_QueryInterface
,
2772 DS8BufferProp_AddRef
,
2773 DS8BufferProp_Release
,
2776 DS8BufferProp_QuerySupport