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 IDirectSoundBufferVtbl DSBuffer_Vtbl
;
80 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
;
81 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
;
82 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
;
85 static inline DS8Buffer
*impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8
*iface
)
87 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer8_iface
);
90 static inline DS8Buffer
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
92 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer_iface
);
95 static inline DS8Buffer
*impl_from_IDirectSound3DBuffer(IDirectSound3DBuffer
*iface
)
97 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSound3DBuffer_iface
);
100 static inline DS8Buffer
*impl_from_IDirectSoundNotify(IDirectSoundNotify
*iface
)
102 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundNotify_iface
);
105 static inline DS8Buffer
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
107 return CONTAINING_RECORD(iface
, DS8Buffer
, IKsPropertySet_iface
);
111 static void CALLBACK
DS8Buffer_timer(UINT timerID
, UINT msg
, DWORD_PTR dwUser
,
112 DWORD_PTR dw1
, DWORD_PTR dw2
)
118 PostThreadMessageA(dwUser
, WM_USER
, 0, 0);
121 static void DS8Buffer_starttimer(DS8Primary
*prim
)
123 DWORD triggertime
, res
= DS_TIME_RES
;
124 ALint refresh
= FAKE_REFRESH_COUNT
;
130 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
132 alcGetIntegerv(prim
->parent
->device
, ALC_REFRESH
, 1, &refresh
);
133 getALCError(prim
->parent
->device
);
135 triggertime
= 1000 / refresh
/ 2;
136 if(triggertime
< time
.wPeriodMin
)
137 triggertime
= time
.wPeriodMin
;
138 TRACE("Calling timer every %"LONGFMT
"u ms for %i refreshes per second\n", triggertime
, refresh
);
140 if (res
< time
.wPeriodMin
)
141 res
= time
.wPeriodMin
;
142 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
143 WARN("Could not set minimum resolution, don't expect sound\n");
145 prim
->timer_res
= res
;
146 prim
->timer_id
= timeSetEvent(triggertime
, res
, DS8Buffer_timer
, prim
->thread_id
, TIME_PERIODIC
|TIME_KILL_SYNCHRONOUS
);
149 /* Should be called with critsect held and context set.. */
150 static void DS8Buffer_addnotify(DS8Buffer
*buf
)
155 list
= buf
->primary
->notifies
;
156 for(i
= 0; i
< buf
->primary
->nnotifies
; ++i
)
160 ERR("Buffer %p already in notification list\n", buf
);
164 if(buf
->primary
->nnotifies
== buf
->primary
->sizenotifies
)
166 list
= HeapReAlloc(GetProcessHeap(), 0, list
, (buf
->primary
->nnotifies
+ 1) * sizeof(*list
));
169 buf
->primary
->sizenotifies
++;
171 list
[buf
->primary
->nnotifies
++] = buf
;
172 buf
->primary
->notifies
= list
;
176 static const char *get_fmtstr_PCM(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
178 out
->Format
= *format
;
179 out
->Format
.cbSize
= 0;
181 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
182 !prim
->SupportedExt
[EXT_MCFORMATS
])
184 WARN("Multi-channel not available\n");
188 if(format
->wBitsPerSample
== 8)
190 switch(format
->nChannels
)
192 case 1: return "AL_FORMAT_MONO8";
193 case 2: return "AL_FORMAT_STEREO8";
194 case 4: return "AL_FORMAT_QUAD8";
195 case 6: return "AL_FORMAT_51CHN8";
196 case 7: return "AL_FORMAT_61CHN8";
197 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";
213 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
214 format
->wBitsPerSample
, format
->nChannels
);
217 static ALenum
get_fmt_PCM(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
219 out
->Format
= *format
;
220 out
->Format
.cbSize
= 0;
222 if(format
->wBitsPerSample
== 8)
224 *in_type
= AL_UNSIGNED_BYTE
;
225 switch(format
->nChannels
)
227 case 1: *in_chans
= AL_MONO
;
229 case 2: *in_chans
= AL_STEREO
;
231 case 4: *in_chans
= AL_QUAD
;
233 case 6: *in_chans
= AL_5POINT1
;
235 case 7: *in_chans
= AL_6POINT1
;
237 case 8: *in_chans
= AL_7POINT1
;
241 else if(format
->wBitsPerSample
== 16)
244 switch(format
->nChannels
)
246 case 1: *in_chans
= AL_MONO
;
248 case 2: *in_chans
= AL_STEREO
;
250 case 4: *in_chans
= AL_QUAD
;
252 case 6: *in_chans
= AL_5POINT1
;
253 return AL_5POINT1_16
;
254 case 7: *in_chans
= AL_6POINT1
;
255 return AL_6POINT1_16
;
256 case 8: *in_chans
= AL_7POINT1
;
257 return AL_7POINT1_16
;
260 #if 0 /* Will cause incorrect byte offsets */
261 else if(format
->wBitsPerSample
== 24)
264 switch(format
->nChannels
)
266 case 1: *in_chans
= AL_MONO
;
268 case 2: *in_chans
= AL_STEREO
;
270 case 4: *in_chans
= AL_QUAD
;
272 case 6: *in_chans
= AL_5POINT1
;
273 return AL_5POINT1_32F
;
274 case 7: *in_chans
= AL_6POINT1
;
275 return AL_6POINT1_32F
;
276 case 8: *in_chans
= AL_7POINT1
;
277 return AL_7POINT1_32F
;
281 else if(format
->wBitsPerSample
== 32)
284 switch(format
->nChannels
)
286 case 1: *in_chans
= AL_MONO
;
288 case 2: *in_chans
= AL_STEREO
;
290 case 4: *in_chans
= AL_QUAD
;
292 case 6: *in_chans
= AL_5POINT1
;
293 return AL_5POINT1_32F
;
294 case 7: *in_chans
= AL_6POINT1
;
295 return AL_6POINT1_32F
;
296 case 8: *in_chans
= AL_7POINT1
;
297 return AL_7POINT1_32F
;
301 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
302 format
->wBitsPerSample
, format
->nChannels
);
306 static const char *get_fmtstr_FLOAT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
308 out
->Format
= *format
;
309 out
->Format
.cbSize
= 0;
311 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
312 !prim
->SupportedExt
[EXT_MCFORMATS
])
314 WARN("Multi-channel not available\n");
318 if(format
->wBitsPerSample
== 32 && prim
->SupportedExt
[EXT_FLOAT32
])
320 switch(format
->nChannels
)
322 case 1: return "AL_FORMAT_MONO_FLOAT32";
323 case 2: return "AL_FORMAT_STEREO_FLOAT32";
324 case 4: return "AL_FORMAT_QUAD32";
325 case 6: return "AL_FORMAT_51CHN32";
326 case 7: return "AL_FORMAT_61CHN32";
327 case 8: return "AL_FORMAT_71CHN32";
331 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
332 format
->wBitsPerSample
, format
->nChannels
);
335 static ALenum
get_fmt_FLOAT(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
337 out
->Format
= *format
;
338 out
->Format
.cbSize
= 0;
340 if(format
->wBitsPerSample
== 32)
343 switch(format
->nChannels
)
345 case 1: *in_chans
= AL_MONO
;
347 case 2: *in_chans
= AL_STEREO
;
349 case 4: *in_chans
= AL_QUAD
;
351 case 6: *in_chans
= AL_5POINT1
;
352 return AL_5POINT1_32F
;
353 case 7: *in_chans
= AL_6POINT1
;
354 return AL_6POINT1_32F
;
355 case 8: *in_chans
= AL_7POINT1
;
356 return AL_7POINT1_32F
;
359 #if 0 /* Will cause incorrect byte offsets */
360 else if(format
->wBitsPerSample
== 64)
362 *in_type
= AL_DOUBLE
;
363 switch(format
->nChannels
)
365 case 1: *in_chans
= AL_MONO
;
367 case 2: *in_chans
= AL_STEREO
;
369 case 4: *in_chans
= AL_QUAD
;
371 case 6: *in_chans
= AL_5POINT1
;
372 return AL_5POINT1_32F
;
373 case 7: *in_chans
= AL_6POINT1
;
374 return AL_6POINT1_32F
;
375 case 8: *in_chans
= AL_7POINT1
;
376 return AL_7POINT1_32F
;
381 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
382 format
->wBitsPerSample
, format
->nChannels
);
386 /* Speaker configs */
387 #define MONO SPEAKER_FRONT_CENTER
388 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
389 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
390 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
391 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
392 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
393 #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)
395 static const char *get_fmtstr_EXT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
397 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
398 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
400 if(!out
->Samples
.wValidBitsPerSample
)
401 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
402 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
404 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
408 if(out
->dwChannelMask
!= MONO
&& out
->dwChannelMask
!= STEREO
&&
409 !prim
->SupportedExt
[EXT_MCFORMATS
])
411 WARN("Multi-channel not available\n");
415 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
417 if(out
->Samples
.wValidBitsPerSample
== 8)
419 switch(out
->dwChannelMask
)
421 case MONO
: return "AL_FORMAT_MONO8";
422 case STEREO
: return "AL_FORMAT_STEREO8";
423 case REAR
: return "AL_FORMAT_REAR8";
424 case QUAD
: return "AL_FORMAT_QUAD8";
425 case X5DOT1
: return "AL_FORMAT_51CHN8";
426 case X6DOT1
: return "AL_FORMAT_61CHN8";
427 case X7DOT1
: return "AL_FORMAT_71CHN8";
430 else if(out
->Samples
.wValidBitsPerSample
== 16)
432 switch(out
->dwChannelMask
)
434 case MONO
: return "AL_FORMAT_MONO16";
435 case STEREO
: return "AL_FORMAT_STEREO16";
436 case REAR
: return "AL_FORMAT_REAR16";
437 case QUAD
: return "AL_FORMAT_QUAD16";
438 case X5DOT1
: return "AL_FORMAT_51CHN16";
439 case X6DOT1
: return "AL_FORMAT_61CHN16";
440 case X7DOT1
: return "AL_FORMAT_71CHN16";
444 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#"LONGFMT
"x)\n",
445 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
448 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
449 prim
->SupportedExt
[EXT_FLOAT32
])
451 if(out
->Samples
.wValidBitsPerSample
== 32)
453 switch(out
->dwChannelMask
)
455 case MONO
: return "AL_FORMAT_MONO_FLOAT32";
456 case STEREO
: return "AL_FORMAT_STEREO_FLOAT32";
457 case REAR
: return "AL_FORMAT_REAR32";
458 case QUAD
: return "AL_FORMAT_QUAD32";
459 case X5DOT1
: return "AL_FORMAT_51CHN32";
460 case X6DOT1
: return "AL_FORMAT_61CHN32";
461 case X7DOT1
: return "AL_FORMAT_71CHN32";
466 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
470 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#"LONGFMT
"x)\n",
471 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
474 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
475 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
478 static ALenum
get_fmt_EXT(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
480 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
481 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
483 if(!out
->Samples
.wValidBitsPerSample
)
484 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
485 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
487 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
491 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
493 if(out
->Samples
.wValidBitsPerSample
== 8)
495 *in_type
= AL_UNSIGNED_BYTE
;
496 switch(out
->dwChannelMask
)
498 case MONO
: *in_chans
= AL_MONO
;
500 case STEREO
: *in_chans
= AL_STEREO
;
502 case REAR
: *in_chans
= AL_REAR
;
504 case QUAD
: *in_chans
= AL_QUAD
;
506 case X5DOT1
: *in_chans
= AL_5POINT1
;
508 case X6DOT1
: *in_chans
= AL_6POINT1
;
510 case X7DOT1
: *in_chans
= AL_7POINT1
;
514 else if(out
->Samples
.wValidBitsPerSample
== 16)
517 switch(out
->dwChannelMask
)
519 case MONO
: *in_chans
= AL_MONO
;
521 case STEREO
: *in_chans
= AL_STEREO
;
523 case REAR
: *in_chans
= AL_REAR
;
525 case QUAD
: *in_chans
= AL_QUAD
;
527 case X5DOT1
: *in_chans
= AL_5POINT1
;
528 return AL_5POINT1_16
;
529 case X6DOT1
: *in_chans
= AL_6POINT1
;
530 return AL_6POINT1_16
;
531 case X7DOT1
: *in_chans
= AL_7POINT1
;
532 return AL_7POINT1_16
;
536 else if(out
->Samples
.wValidBitsPerSample
== 24)
539 switch(out
->dwChannelMask
)
541 case MONO
: *in_chans
= AL_MONO
;
543 case STEREO
: *in_chans
= AL_STEREO
;
545 case REAR
: *in_chans
= AL_REAR
;
547 case QUAD
: *in_chans
= AL_QUAD
;
549 case X5DOT1
: *in_chans
= AL_5POINT1
;
550 return AL_5POINT1_32F
;
551 case X6DOT1
: *in_chans
= AL_6POINT1
;
552 return AL_6POINT1_32F
;
553 case X7DOT1
: *in_chans
= AL_7POINT1
;
554 return AL_7POINT1_32F
;
558 else if(out
->Samples
.wValidBitsPerSample
== 32)
561 switch(out
->dwChannelMask
)
563 case MONO
: *in_chans
= AL_MONO
;
565 case STEREO
: *in_chans
= AL_STEREO
;
567 case REAR
: *in_chans
= AL_REAR
;
569 case QUAD
: *in_chans
= AL_QUAD
;
571 case X5DOT1
: *in_chans
= AL_5POINT1
;
572 return AL_5POINT1_32F
;
573 case X6DOT1
: *in_chans
= AL_6POINT1
;
574 return AL_6POINT1_32F
;
575 case X7DOT1
: *in_chans
= AL_7POINT1
;
576 return AL_7POINT1_32F
;
580 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#"LONGFMT
"x)\n",
581 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
584 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
586 if(out
->Samples
.wValidBitsPerSample
== 32)
589 switch(out
->dwChannelMask
)
591 case MONO
: *in_chans
= AL_MONO
;
593 case STEREO
: *in_chans
= AL_STEREO
;
595 case REAR
: *in_chans
= AL_REAR
;
597 case QUAD
: *in_chans
= AL_QUAD
;
599 case X5DOT1
: *in_chans
= AL_5POINT1
;
600 return AL_5POINT1_32F
;
601 case X6DOT1
: *in_chans
= AL_6POINT1
;
602 return AL_6POINT1_32F
;
603 case X7DOT1
: *in_chans
= AL_7POINT1
;
604 return AL_7POINT1_32F
;
608 else if(out
->Samples
.wValidBitsPerSample
== 64)
610 *in_type
= AL_DOUBLE
;
611 switch(out
->dwChannelMask
)
613 case MONO
: *in_chans
= AL_MONO
;
615 case STEREO
: *in_chans
= AL_STEREO
;
617 case REAR
: *in_chans
= AL_REAR
;
619 case QUAD
: *in_chans
= AL_QUAD
;
621 case X5DOT1
: *in_chans
= AL_5POINT1
;
622 return AL_5POINT1_32F
;
623 case X6DOT1
: *in_chans
= AL_6POINT1
;
624 return AL_6POINT1_32F
;
625 case X7DOT1
: *in_chans
= AL_7POINT1
;
626 return AL_7POINT1_32F
;
632 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
636 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#"LONGFMT
"x)\n",
637 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
640 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
641 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
645 static void DS8Data_Release(DS8Data
*This
);
646 static HRESULT
DS8Data_Create(DS8Data
**ppv
, const DSBUFFERDESC
*desc
, DS8Primary
*prim
)
648 HRESULT hr
= DSERR_INVALIDPARAM
;
649 const WAVEFORMATEX
*format
;
652 format
= desc
->lpwfxFormat
;
653 TRACE("Requested buffer format:\n"
654 " FormatTag = 0x%04x\n"
656 " SamplesPerSec = %"LONGFMT
"u\n"
657 " AvgBytesPerSec = %"LONGFMT
"u\n"
659 " BitsPerSample = %d\n",
660 format
->wFormatTag
, format
->nChannels
,
661 format
->nSamplesPerSec
, format
->nAvgBytesPerSec
,
662 format
->nBlockAlign
, format
->wBitsPerSample
);
664 if(format
->nBlockAlign
== 0)
666 WARN("Invalid BlockAlign specified\n");
667 return DSERR_INVALIDPARAM
;
670 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
671 * will need the EAX-RAM extension. Currently, we just tell the app it
672 * gets what it wanted. */
673 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
));
675 return E_OUTOFMEMORY
;
678 pBuffer
->dsbflags
= desc
->dwFlags
;
679 if((pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
)) == (DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
))
681 WARN("Hardware and software location requested\n");
684 if(!(pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCDEFER
)))
685 pBuffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
687 pBuffer
->buf_size
= desc
->dwBufferBytes
+ format
->nBlockAlign
- 1;
688 pBuffer
->buf_size
-= pBuffer
->buf_size
%format
->nBlockAlign
;
690 hr
= DSERR_BUFFERTOOSMALL
;
691 if(pBuffer
->buf_size
< DSBSIZE_MIN
)
694 hr
= DSERR_INVALIDPARAM
;
695 if(pBuffer
->buf_size
> DSBSIZE_MAX
)
698 pBuffer
->numsegs
= 1;
699 pBuffer
->segsize
= pBuffer
->buf_size
;
700 pBuffer
->lastsegsize
= pBuffer
->buf_size
;
702 if(!prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
704 const char *fmt_str
= NULL
;
706 if(!(pBuffer
->dsbflags
&DSBCAPS_STATIC
) && !prim
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] &&
707 !prim
->SupportedExt
[EXT_STATIC_BUFFER
])
709 ALCint refresh
= FAKE_REFRESH_COUNT
;
712 alcGetIntegerv(prim
->parent
->device
, ALC_REFRESH
, 1, &refresh
);
713 getALCError(prim
->parent
->device
);
715 newSize
= format
->nAvgBytesPerSec
/refresh
+ format
->nBlockAlign
- 1;
716 newSize
-= newSize
%format
->nBlockAlign
;
718 /* Make sure enough buffers are available */
719 if(newSize
> pBuffer
->buf_size
/(QBUFFERS
+2))
720 ERR("Buffer segments too large to stream (%u for %u)!\n",
721 newSize
, pBuffer
->buf_size
);
724 pBuffer
->numsegs
= pBuffer
->buf_size
/newSize
;
725 pBuffer
->segsize
= newSize
;
726 pBuffer
->lastsegsize
= pBuffer
->buf_size
- (newSize
*(pBuffer
->numsegs
-1));
727 TRACE("New streaming buffer (%u chunks, %u : %u sizes)\n",
728 pBuffer
->numsegs
, pBuffer
->segsize
, pBuffer
->lastsegsize
);
732 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
733 fmt_str
= get_fmtstr_PCM(prim
, format
, &pBuffer
->format
);
734 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
735 fmt_str
= get_fmtstr_FLOAT(prim
, format
, &pBuffer
->format
);
736 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
738 const WAVEFORMATEXTENSIBLE
*wfe
;
740 hr
= DSERR_CONTROLUNAVAIL
;
741 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
742 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
745 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
746 TRACE("Extensible values:\n"
748 " ChannelMask = 0x%"LONGFMT
"x\n"
750 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
751 debugstr_guid(&wfe
->SubFormat
));
753 fmt_str
= get_fmtstr_EXT(prim
, format
, &pBuffer
->format
);
756 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
758 hr
= DSERR_INVALIDCALL
;
762 pBuffer
->buf_format
= alGetEnumValue(fmt_str
);
763 if(alGetError() != AL_NO_ERROR
|| pBuffer
->buf_format
== 0 ||
764 pBuffer
->buf_format
== -1)
766 WARN("Could not get OpenAL format from %s\n", fmt_str
);
772 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
773 pBuffer
->buf_format
= get_fmt_PCM(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
774 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
775 pBuffer
->buf_format
= get_fmt_FLOAT(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
776 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
778 const WAVEFORMATEXTENSIBLE
*wfe
;
780 hr
= DSERR_CONTROLUNAVAIL
;
781 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
782 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
785 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
786 TRACE("Extensible values:\n"
788 " ChannelMask = 0x%"LONGFMT
"x\n"
790 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
791 debugstr_guid(&wfe
->SubFormat
));
793 pBuffer
->buf_format
= get_fmt_EXT(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
796 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
798 hr
= DSERR_INVALIDCALL
;
799 if(prim
->ExtAL
.IsBufferFormatSupportedSOFT(pBuffer
->buf_format
) == AL_FALSE
)
801 WARN("Unsupported OpenAL format: 0x%x\n", pBuffer
->buf_format
);
807 pBuffer
->buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
->buffers
)*pBuffer
->numsegs
);
808 pBuffer
->data
= HeapAlloc(GetProcessHeap(), 0, pBuffer
->buf_size
);
809 if(!pBuffer
->buffers
|| !pBuffer
->data
)
812 alGenBuffers(pBuffer
->numsegs
, pBuffer
->buffers
);
819 DS8Data_Release(pBuffer
);
823 static void DS8Data_AddRef(DS8Data
*data
)
825 InterlockedIncrement(&data
->ref
);
828 /* This function is always called with the device lock held */
829 static void DS8Data_Release(DS8Data
*This
)
831 if(InterlockedDecrement(&This
->ref
)) return;
833 TRACE("Deleting %p\n", This
);
834 if (This
->buffers
&& This
->buffers
[0])
836 alDeleteBuffers(This
->numsegs
, This
->buffers
);
839 HeapFree(GetProcessHeap(), 0, This
->buffers
);
840 HeapFree(GetProcessHeap(), 0, This
->data
);
841 HeapFree(GetProcessHeap(), 0, This
);
844 HRESULT
DS8Buffer_Create(DS8Buffer
**ppv
, DS8Primary
*prim
, IDirectSoundBuffer
*orig
)
850 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
851 if(!This
) return DSERR_OUTOFMEMORY
;
853 This
->IDirectSoundBuffer8_iface
.lpVtbl
= (IDirectSoundBuffer8Vtbl
*)&DS8Buffer_Vtbl
;
854 This
->IDirectSoundBuffer_iface
.lpVtbl
= (IDirectSoundBufferVtbl
*)&DSBuffer_Vtbl
;
855 This
->IDirectSound3DBuffer_iface
.lpVtbl
= (IDirectSound3DBufferVtbl
*)&DS8Buffer3d_Vtbl
;
856 This
->IDirectSoundNotify_iface
.lpVtbl
= (IDirectSoundNotifyVtbl
*)&DS8BufferNot_Vtbl
;
857 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8BufferProp_Vtbl
;
859 This
->primary
= prim
;
860 This
->ctx
= prim
->ctx
;
861 This
->ExtAL
= &prim
->ExtAL
;
862 This
->crst
= &prim
->crst
;
863 This
->ref
= This
->all_ref
= 1;
867 DS8Buffer
*org
= impl_from_IDirectSoundBuffer(orig
);
868 hr
= DSERR_BUFFERLOST
;
871 DS8Data_AddRef(org
->buffer
);
872 This
->buffer
= org
->buffer
;
875 /* Append to buffer list */
876 if(prim
->nbuffers
== prim
->sizebuffers
)
880 hr
= DSERR_OUTOFMEMORY
;
881 bufs
= HeapReAlloc(GetProcessHeap(), 0, prim
->buffers
, sizeof(*bufs
)*(prim
->nbuffers
+1));
884 prim
->buffers
= bufs
;
887 prim
->buffers
[prim
->nbuffers
++] = This
;
889 /* Disable until initialized.. */
890 This
->ds3dmode
= DS3DMODE_DISABLE
;
896 DS8Buffer_Destroy(This
);
900 void DS8Buffer_Destroy(DS8Buffer
*This
)
902 DS8Primary
*prim
= This
->primary
;
905 TRACE("Destroying %p\n", This
);
907 EnterCriticalSection(&prim
->crst
);
908 /* Remove from list, if in list */
909 for(idx
= 0;idx
< prim
->nnotifies
;++idx
)
911 if(This
== prim
->notifies
[idx
])
913 prim
->notifies
[idx
] = prim
->notifies
[--prim
->nnotifies
];
917 for(idx
= 0;idx
< prim
->nbuffers
;++idx
)
919 if(prim
->buffers
[idx
] == This
)
921 prim
->buffers
[idx
] = prim
->buffers
[--prim
->nbuffers
];
926 setALContext(This
->ctx
);
931 alSourceStop(This
->source
);
932 alSourcei(This
->source
, AL_BUFFER
, 0);
935 sources
= prim
->sources
;
936 if(prim
->nsources
== prim
->sizesources
)
938 sources
= HeapReAlloc(GetProcessHeap(), 0, sources
, sizeof(*sources
)*(prim
->nsources
+1));
940 alDeleteSources(1, &This
->source
);
946 sources
[prim
->nsources
++] = This
->source
;
947 prim
->sources
= sources
;
951 LeaveCriticalSection(&prim
->crst
);
954 DS8Data_Release(This
->buffer
);
958 HeapFree(GetProcessHeap(), 0, This
->notify
);
959 HeapFree(GetProcessHeap(), 0, This
);
963 static HRESULT WINAPI
DS8Buffer_QueryInterface(IDirectSoundBuffer8
*iface
, REFIID riid
, void **ppv
)
965 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
967 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
970 if(IsEqualIID(riid
, &IID_IUnknown
))
971 *ppv
= &This
->IDirectSoundBuffer8_iface
;
972 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
973 *ppv
= &This
->IDirectSoundBuffer_iface
;
974 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer8
))
976 if(This
->primary
->parent
->is_8
)
977 *ppv
= &This
->IDirectSoundBuffer8_iface
;
979 else if(IsEqualIID(riid
, &IID_IDirectSound3DBuffer
))
981 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
982 *ppv
= &This
->IDirectSound3DBuffer_iface
;
984 else if(IsEqualIID(riid
, &IID_IDirectSoundNotify
))
986 if((This
->buffer
->dsbflags
&DSBCAPS_CTRLPOSITIONNOTIFY
))
987 *ppv
= &This
->IDirectSoundNotify_iface
;
989 else if(IsEqualIID(riid
, &IID_IKsPropertySet
))
990 *ppv
= &This
->IKsPropertySet_iface
;
992 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
996 IUnknown_AddRef((IUnknown
*)*ppv
);
1000 return E_NOINTERFACE
;
1003 static ULONG WINAPI
DS8Buffer_AddRef(IDirectSoundBuffer8
*iface
)
1005 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1008 InterlockedIncrement(&This
->all_ref
);
1009 ret
= InterlockedIncrement(&This
->ref
);
1010 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1015 static ULONG WINAPI
DS8Buffer_Release(IDirectSoundBuffer8
*iface
)
1017 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1020 ret
= InterlockedDecrement(&This
->ref
);
1021 TRACE("new refcount %"LONGFMT
"d\n", ret
);
1022 if(InterlockedDecrement(&This
->all_ref
) == 0)
1023 DS8Buffer_Destroy(This
);
1028 static HRESULT WINAPI
DS8Buffer_GetCaps(IDirectSoundBuffer8
*iface
, DSBCAPS
*caps
)
1030 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1032 TRACE("(%p)->(%p)\n", iface
, caps
);
1034 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
1036 WARN("Invalid DSBCAPS (%p, %"LONGFMT
"u)\n", caps
, (caps
? caps
->dwSize
: 0));
1037 return DSERR_INVALIDPARAM
;
1040 caps
->dwFlags
= This
->buffer
->dsbflags
;
1041 caps
->dwBufferBytes
= This
->buffer
->buf_size
;
1042 caps
->dwUnlockTransferRate
= 4096;
1043 caps
->dwPlayCpuOverhead
= 0;
1047 static HRESULT WINAPI
DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD
*playpos
, DWORD
*curpos
)
1049 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1050 WAVEFORMATEX
*format
= &This
->buffer
->format
.Format
;
1051 UINT writecursor
, pos
;
1053 TRACE("(%p)->(%p, %p)\n", iface
, playpos
, curpos
);
1055 EnterCriticalSection(This
->crst
);
1056 setALContext(This
->ctx
);
1058 if(This
->buffer
->numsegs
> 1)
1060 ALint queued
= QBUFFERS
;
1061 alGetSourcei(This
->source
, AL_BUFFERS_QUEUED
, &queued
);
1064 pos
= (This
->curidx
+This
->buffer
->numsegs
-queued
)%This
->buffer
->numsegs
;
1065 pos
*= This
->buffer
->segsize
;
1066 writecursor
= This
->curidx
* This
->buffer
->segsize
;
1068 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] ||
1069 This
->primary
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
1071 ALint rwpos
[2] = { 0, 0 };
1073 alGetSourceiv(This
->source
, AL_BYTE_RW_OFFSETS_SOFT
, rwpos
);
1077 writecursor
= rwpos
[1];
1084 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
1085 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
1089 if(status
== AL_PLAYING
)
1091 writecursor
= format
->nSamplesPerSec
/ 100;
1092 writecursor
*= format
->nBlockAlign
;
1096 writecursor
= (writecursor
+ pos
) % This
->buffer
->buf_size
;
1098 TRACE("%p Play pos = %u, write pos = %u\n", This
, pos
, writecursor
);
1099 if(pos
>= This
->buffer
->buf_size
)
1101 ERR("playpos >= buf_size\n");
1102 pos
%= This
->buffer
->buf_size
;
1104 if(writecursor
>= This
->buffer
->buf_size
)
1106 ERR("writepos >= buf_size\n");
1107 writecursor
%= This
->buffer
->buf_size
;
1110 if(playpos
) *playpos
= pos
;
1111 if(curpos
) *curpos
= writecursor
;
1114 LeaveCriticalSection(This
->crst
);
1119 static HRESULT WINAPI
DS8Buffer_GetFormat(IDirectSoundBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
1121 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1125 TRACE("(%p)->(%p, %"LONGFMT
"u, %p)\n", iface
, wfx
, allocated
, written
);
1127 if(!wfx
&& !written
)
1129 WARN("Cannot report format or format size\n");
1130 return DSERR_INVALIDPARAM
;
1133 size
= sizeof(This
->buffer
->format
.Format
) + This
->buffer
->format
.Format
.cbSize
;
1136 if(allocated
< size
)
1137 hr
= DSERR_INVALIDPARAM
;
1139 memcpy(wfx
, &This
->buffer
->format
.Format
, size
);
1147 static HRESULT WINAPI
DS8Buffer_GetVolume(IDirectSoundBuffer8
*iface
, LONG
*vol
)
1149 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1152 TRACE("(%p)->(%p)\n", iface
, vol
);
1156 WARN("Invalid pointer\n");
1157 return DSERR_INVALIDPARAM
;
1160 hr
= DSERR_CONTROLUNAVAIL
;
1161 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1162 WARN("Volume control not set\n");
1165 ALfloat gain
= 1.0f
;
1167 setALContext(This
->ctx
);
1168 alGetSourcef(This
->source
, AL_GAIN
, &gain
);
1172 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
1179 static HRESULT WINAPI
DS8Buffer_GetPan(IDirectSoundBuffer8
*iface
, LONG
*pan
)
1181 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1184 TRACE("(%p)->(%p)\n", iface
, pan
);
1188 WARN("Invalid pointer\n");
1189 return DSERR_INVALIDPARAM
;
1192 hr
= DSERR_CONTROLUNAVAIL
;
1193 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1194 WARN("Panning control not set\n");
1199 setALContext(This
->ctx
);
1200 alGetSourcefv(This
->source
, AL_POSITION
, pos
);
1204 *pan
= clampI(((pos
[0]+1.0) * (DSBPAN_RIGHT
-DSBPAN_LEFT
) / 2.0 + 0.5) + DSBPAN_LEFT
, DSBPAN_LEFT
, DSBPAN_RIGHT
);
1211 static HRESULT WINAPI
DS8Buffer_GetFrequency(IDirectSoundBuffer8
*iface
, DWORD
*freq
)
1213 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1216 TRACE("(%p)->(%p)\n", iface
, freq
);
1220 WARN("Invalid pointer\n");
1221 return DSERR_INVALIDPARAM
;
1224 hr
= DSERR_CONTROLUNAVAIL
;
1225 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1226 WARN("Frequency control not set\n");
1229 ALfloat pitch
= 1.0f
;
1231 setALContext(This
->ctx
);
1232 alGetSourcefv(This
->source
, AL_PITCH
, &pitch
);
1236 *freq
= (DWORD
)(This
->buffer
->format
.Format
.nSamplesPerSec
* pitch
);
1243 static HRESULT WINAPI
DS8Buffer_GetStatus(IDirectSoundBuffer8
*iface
, DWORD
*status
)
1245 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1246 ALint state
, looping
;
1248 TRACE("(%p)->(%p)\n", iface
, status
);
1252 WARN("Invalid pointer\n");
1253 return DSERR_INVALIDPARAM
;
1256 EnterCriticalSection(This
->crst
);
1258 setALContext(This
->ctx
);
1259 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1260 looping
= This
->islooping
;
1261 if(This
->buffer
->numsegs
== 1)
1262 alGetSourcei(This
->source
, AL_LOOPING
, &looping
);
1263 else if(state
!= AL_PLAYING
)
1264 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1268 LeaveCriticalSection(This
->crst
);
1271 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1273 if((This
->buffer
->dsbflags
&DSBCAPS_LOCSOFTWARE
))
1274 *status
|= DSBSTATUS_LOCSOFTWARE
;
1275 else if((This
->buffer
->dsbflags
&DSBCAPS_LOCHARDWARE
))
1276 *status
|= DSBSTATUS_LOCHARDWARE
;
1278 if(state
== AL_PLAYING
)
1279 *status
|= DSBSTATUS_PLAYING
| (looping
? DSBSTATUS_LOOPING
: 0);
1284 static HRESULT WINAPI
DS8Buffer_Initialize(IDirectSoundBuffer8
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
1286 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1287 DS3DBUFFER
*ds3dbuffer
;
1290 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
1292 EnterCriticalSection(This
->crst
);
1293 setALContext(This
->ctx
);
1295 hr
= DSERR_ALREADYINITIALIZED
;
1301 hr
= DSERR_INVALIDPARAM
;
1304 WARN("Missing DSound buffer description\n");
1307 if(!desc
->lpwfxFormat
)
1309 WARN("Missing buffer format (%p)\n", This
);
1312 if((desc
->dwFlags
&DSBCAPS_CTRL3D
) && desc
->lpwfxFormat
->nChannels
!= 1)
1314 if(This
->primary
->parent
->is_8
)
1316 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
1318 WARN("Can't create multi-channel 3D buffers\n");
1321 ERR("Multi-channel 3D sounds are not spatialized\n");
1324 hr
= DS8Data_Create(&This
->buffer
, desc
, This
->primary
);
1329 DS8Data
*buf
= This
->buffer
;
1331 if(buf
->format
.Format
.wBitsPerSample
== 8)
1332 memset(buf
->data
, 0x80, buf
->buf_size
);
1334 memset(buf
->data
, 0x00, buf
->buf_size
);
1336 if(This
->primary
->SupportedExt
[EXT_STATIC_BUFFER
])
1337 This
->ExtAL
->BufferDataStatic(buf
->buffers
[0], buf
->buf_format
,
1338 buf
->data
, buf
->buf_size
,
1339 buf
->format
.Format
.nSamplesPerSec
);
1340 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
1341 This
->ExtAL
->BufferSamplesSOFT(buf
->buffers
[0],
1342 buf
->format
.Format
.nSamplesPerSec
, buf
->buf_format
,
1343 buf
->buf_size
/buf
->format
.Format
.nBlockAlign
,
1344 buf
->in_chans
, buf
->in_type
, buf
->data
);
1345 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SUB_DATA
])
1346 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1347 buf
->data
, buf
->buf_size
,
1348 buf
->format
.Format
.nSamplesPerSec
);
1354 if(This
->primary
->nsources
)
1356 This
->source
= This
->primary
->sources
[--This
->primary
->nsources
];
1357 alSourcef(This
->source
, AL_GAIN
, 1.0f
);
1358 alSourcef(This
->source
, AL_PITCH
, 1.0f
);
1363 alGenSources(1, &This
->source
);
1364 if(alGetError() != AL_NO_ERROR
)
1368 ds3dbuffer
= &This
->ds3dbuffer
;
1369 ds3dbuffer
->dwSize
= sizeof(*ds3dbuffer
);
1370 ds3dbuffer
->vPosition
.x
= 0.0;
1371 ds3dbuffer
->vPosition
.y
= 0.0;
1372 ds3dbuffer
->vPosition
.z
= 0.0;
1373 ds3dbuffer
->vVelocity
.x
= 0.0;
1374 ds3dbuffer
->vVelocity
.y
= 0.0;
1375 ds3dbuffer
->vVelocity
.z
= 0.0;
1376 ds3dbuffer
->dwInsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1377 ds3dbuffer
->dwOutsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1378 ds3dbuffer
->vConeOrientation
.x
= 0.0;
1379 ds3dbuffer
->vConeOrientation
.y
= 0.0;
1380 ds3dbuffer
->vConeOrientation
.z
= 1.0;
1381 ds3dbuffer
->lConeOutsideVolume
= DS3D_DEFAULTCONEOUTSIDEVOLUME
;
1382 ds3dbuffer
->flMinDistance
= DS3D_DEFAULTMINDISTANCE
;
1383 ds3dbuffer
->flMaxDistance
= DS3D_DEFAULTMAXDISTANCE
;
1384 ds3dbuffer
->dwMode
= DS3DMODE_NORMAL
;
1386 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
1388 if(This
->primary
->auxslot
!= 0)
1390 alSource3i(This
->source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1394 hr
= IDirectSound3DBuffer_SetAllParameters(&This
->IDirectSound3DBuffer_iface
, ds3dbuffer
, DS3D_IMMEDIATE
);
1397 ERR("SetAllParameters failed\n");
1403 ALuint source
= This
->source
;
1405 if(This
->primary
->auxslot
!= 0)
1407 /* Simple hack to make reverb affect non-3D sounds too */
1408 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1409 /*alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);*/
1412 /* Non-3D sources aren't distance attenuated */
1413 This
->ds3dmode
= DS3DMODE_DISABLE
;
1414 alSource3f(source
, AL_POSITION
, 0.0f
, 1.0f
, 0.0f
);
1415 alSource3f(source
, AL_VELOCITY
, 0.0f
, 0.0f
, 0.0f
);
1416 alSource3f(source
, AL_DIRECTION
, 0.0f
, 0.0f
, 0.0f
);
1417 alSourcef(source
, AL_CONE_OUTER_GAIN
, 1.0f
);
1418 alSourcef(source
, AL_REFERENCE_DISTANCE
, 1.0f
);
1419 alSourcef(source
, AL_MAX_DISTANCE
, 1000.0f
);
1420 alSourcef(source
, AL_ROLLOFF_FACTOR
, 0.0f
);
1421 alSourcei(source
, AL_CONE_INNER_ANGLE
, 360);
1422 alSourcei(source
, AL_CONE_OUTER_ANGLE
, 360);
1423 alSourcei(source
, AL_SOURCE_RELATIVE
, AL_TRUE
);
1430 LeaveCriticalSection(This
->crst
);
1435 static HRESULT WINAPI
DS8Buffer_Lock(IDirectSoundBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1437 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1440 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %p, %p, %p, %p, 0x%"LONGFMT
"x)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1444 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
1445 return DSERR_INVALIDPARAM
;
1450 if(ptr2
) *ptr2
= NULL
;
1453 if((flags
&DSBLOCK_FROMWRITECURSOR
))
1454 DS8Buffer_GetCurrentPosition(iface
, NULL
, &ofs
);
1455 else if(ofs
>= This
->buffer
->buf_size
)
1457 WARN("Invalid ofs %"LONGFMT
"u\n", ofs
);
1458 return DSERR_INVALIDPARAM
;
1460 if((flags
&DSBLOCK_ENTIREBUFFER
))
1461 bytes
= This
->buffer
->buf_size
;
1462 else if(bytes
> This
->buffer
->buf_size
)
1464 WARN("Invalid size %"LONGFMT
"u\n", bytes
);
1465 return DSERR_INVALIDPARAM
;
1468 if(InterlockedExchange(&This
->buffer
->locked
, TRUE
) == TRUE
)
1470 WARN("Already locked\n");
1471 return DSERR_INVALIDPARAM
;
1474 *ptr1
= This
->buffer
->data
+ ofs
;
1475 if(ofs
+bytes
>= This
->buffer
->buf_size
)
1477 *len1
= This
->buffer
->buf_size
- ofs
;
1478 remain
= bytes
- *len1
;
1486 if(ptr2
&& len2
&& remain
)
1488 *ptr2
= This
->buffer
->data
;
1495 static HRESULT WINAPI
DS8Buffer_Play(IDirectSoundBuffer8
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1497 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1498 ALint type
, state
= AL_STOPPED
;
1502 TRACE("%p\n", This
);
1504 EnterCriticalSection(This
->crst
);
1505 setALContext(This
->ctx
);
1507 hr
= DSERR_BUFFERLOST
;
1508 if(This
->bufferlost
)
1510 WARN("Buffer %p lost\n", This
);
1514 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1516 if(!(This
->buffer
->dsbflags
&(DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCSOFTWARE
)))
1518 if(flags
& DSBPLAY_LOCSOFTWARE
)
1519 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1521 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1526 ERR("Invalid priority set for non-deferred buffer %p, %"LONGFMT
"u!\n", This
->buffer
, prio
);
1527 hr
= DSERR_INVALIDPARAM
;
1531 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1532 if(This
->buffer
->numsegs
> 1)
1534 This
->islooping
= !!(flags
&DSBPLAY_LOOPING
);
1535 if(state
!= AL_PLAYING
&& This
->isplaying
)
1540 alGetSourcei(This
->source
, AL_SOURCE_TYPE
, &type
);
1541 alSourcei(This
->source
, AL_LOOPING
, (flags
&DSBPLAY_LOOPING
) ? AL_TRUE
: AL_FALSE
);
1546 if(state
== AL_PLAYING
)
1549 /* alSourceQueueBuffers will implicitly set type to streaming */
1550 if(This
->buffer
->numsegs
== 1)
1552 if(type
!= AL_STATIC
)
1553 alSourcei(This
->source
, AL_BUFFER
, This
->buffer
->buffers
[0]);
1554 alSourcePlay(This
->source
);
1556 if(alGetError() != AL_NO_ERROR
)
1558 ERR("Couldn't start source\n");
1559 This
->curidx
= (This
->buffer
->numsegs
-1+This
->curidx
)%This
->buffer
->numsegs
;
1560 alSourcei(This
->source
, AL_BUFFER
, 0);
1565 This
->isplaying
= TRUE
;
1569 DS8Buffer_addnotify(This
);
1570 DS8Buffer_starttimer(This
->primary
);
1572 else if(This
->buffer
->numsegs
> 1)
1573 DS8Buffer_starttimer(This
->primary
);
1577 LeaveCriticalSection(This
->crst
);
1581 static HRESULT WINAPI
DS8Buffer_SetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD pos
)
1583 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1585 TRACE("(%p)->(%"LONGFMT
"u)\n", iface
, pos
);
1587 if(pos
>= This
->buffer
->buf_size
)
1588 return DSERR_INVALIDPARAM
;
1590 EnterCriticalSection(This
->crst
);
1592 if(This
->buffer
->numsegs
> 1)
1594 DS8Data
*buf
= This
->buffer
;
1595 This
->curidx
= pos
/buf
->segsize
;
1596 if(This
->curidx
>= buf
->numsegs
)
1597 This
->curidx
= buf
->numsegs
- 1;
1600 setALContext(This
->ctx
);
1601 /* Perform a flush, so the next timer update will restart at the
1602 * proper position */
1603 alSourceStop(This
->source
);
1604 alSourcei(This
->source
, AL_BUFFER
, 0);
1611 setALContext(This
->ctx
);
1612 alSourcei(This
->source
, AL_BYTE_OFFSET
, pos
);
1615 This
->lastpos
= pos
;
1617 LeaveCriticalSection(This
->crst
);
1621 static HRESULT WINAPI
DS8Buffer_SetFormat(IDirectSoundBuffer8
*iface
, const WAVEFORMATEX
*wfx
)
1623 /* This call only works on primary buffers */
1624 WARN("(%p)->(%p)\n", iface
, wfx
);
1625 return DSERR_INVALIDCALL
;
1628 static HRESULT WINAPI
DS8Buffer_SetVolume(IDirectSoundBuffer8
*iface
, LONG vol
)
1630 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1633 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, vol
);
1635 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
1637 WARN("Invalid volume (%"LONGFMT
"d)\n", vol
);
1638 return DSERR_INVALIDPARAM
;
1641 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1642 hr
= DSERR_CONTROLUNAVAIL
;
1645 ALfloat fvol
= mB_to_gain(vol
);
1646 setALContext(This
->ctx
);
1647 alSourcef(This
->source
, AL_GAIN
, fvol
);
1654 static HRESULT WINAPI
DS8Buffer_SetPan(IDirectSoundBuffer8
*iface
, LONG pan
)
1656 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1659 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, pan
);
1661 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
1663 WARN("invalid parameter: pan = %"LONGFMT
"d\n", pan
);
1664 return DSERR_INVALIDPARAM
;
1667 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1668 hr
= DSERR_CONTROLUNAVAIL
;
1672 pos
[0] = (pan
-DSBPAN_LEFT
) * 2.0 / (ALfloat
)(DSBPAN_RIGHT
-DSBPAN_LEFT
) - 1.0;
1673 /* NOTE: Strict movement along the X plane can cause the sound to jump
1674 * between left and right sharply. Using a curved path helps smooth it
1676 pos
[1] = sqrt(1.0 - pos
[0]*pos
[0]);
1679 setALContext(This
->ctx
);
1680 alSourcefv(This
->source
, AL_POSITION
, pos
);
1684 if(pan
!= 0 && This
->buffer
->format
.Format
.nChannels
> 1)
1685 FIXME("Panning for multi-channel buffers is not supported\n");
1691 static HRESULT WINAPI
DS8Buffer_SetFrequency(IDirectSoundBuffer8
*iface
, DWORD freq
)
1693 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1696 TRACE("(%p)->(%"LONGFMT
"u)\n", iface
, freq
);
1698 if(freq
< DSBFREQUENCY_MIN
|| freq
> DSBFREQUENCY_MAX
)
1700 WARN("invalid parameter: freq = %"LONGFMT
"u\n", freq
);
1701 return DSERR_INVALIDPARAM
;
1704 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1705 hr
= DSERR_CONTROLUNAVAIL
;
1708 ALfloat pitch
= 1.0f
;
1709 if(freq
!= DSBFREQUENCY_ORIGINAL
)
1710 pitch
= freq
/ (ALfloat
)This
->buffer
->format
.Format
.nSamplesPerSec
;
1712 setALContext(This
->ctx
);
1713 alSourcef(This
->source
, AL_PITCH
, pitch
);
1721 static HRESULT WINAPI
DS8Buffer_Stop(IDirectSoundBuffer8
*iface
)
1723 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1726 TRACE("(%p)->()\n", iface
);
1728 EnterCriticalSection(This
->crst
);
1729 setALContext(This
->ctx
);
1731 alSourcePause(This
->source
);
1733 /* Mac OS X doesn't immediately report state change
1734 * if Play() is immediately called after Stop, this can be fatal,
1735 * the buffer would never be restarted
1739 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1740 if(state
!= AL_PLAYING
)
1745 This
->isplaying
= FALSE
;
1748 LeaveCriticalSection(This
->crst
);
1753 static HRESULT WINAPI
DS8Buffer_Unlock(IDirectSoundBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1755 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1756 DS8Data
*buf
= This
->buffer
;
1757 DWORD bufsize
= buf
->buf_size
;
1758 DWORD_PTR ofs1
, ofs2
;
1759 DWORD_PTR boundary
= (DWORD_PTR
)buf
->data
;
1762 TRACE("(%p)->(%p, %"LONGFMT
"u, %p, %"LONGFMT
"u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1764 if(InterlockedExchange(&This
->buffer
->locked
, FALSE
) == FALSE
)
1766 WARN("Not locked\n");
1767 return DSERR_INVALIDPARAM
;
1770 hr
= DSERR_INVALIDPARAM
;
1771 /* Make sure offset is between boundary and boundary + bufsize */
1772 ofs1
= (DWORD_PTR
)ptr1
;
1773 ofs2
= (DWORD_PTR
)ptr2
;
1776 if(ofs2
&& ofs2
!= boundary
)
1780 if(bufsize
-ofs1
< len1
|| len2
> ofs1
)
1788 if(This
->primary
->SupportedExt
[EXT_STATIC_BUFFER
])
1791 setALContext(This
->ctx
);
1792 if(This
->primary
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
1794 const WAVEFORMATEX
*format
= &buf
->format
.Format
;
1796 ptr1
= (BYTE
*)ptr1
- (ofs1
%format
->nBlockAlign
);
1797 ofs1
/= format
->nBlockAlign
;
1798 len1
/= format
->nBlockAlign
;
1800 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs1
, len1
,
1801 buf
->in_chans
, buf
->in_type
, ptr1
);
1802 ptr2
= (BYTE
*)ptr2
- (ofs2
%format
->nBlockAlign
);
1803 ofs2
/= format
->nBlockAlign
;
1804 len2
/= format
->nBlockAlign
;
1806 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs2
, len2
,
1807 buf
->in_chans
, buf
->in_type
, ptr2
);
1810 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SUB_DATA
])
1812 const WAVEFORMATEX
*format
= &buf
->format
.Format
;
1814 len1
-= len1
%format
->nBlockAlign
;
1816 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr1
,
1818 len2
-= len2
%format
->nBlockAlign
;
1820 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr2
,
1826 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1827 buf
->data
, buf
->buf_size
,
1828 buf
->format
.Format
.nSamplesPerSec
);
1835 WARN("Invalid parameters (0x%lx,%"LONGFMT
"u) (%p,%"LONGFMT
"u,%p,%"LONGFMT
"u)\n", boundary
, bufsize
, ptr1
, len1
, ptr2
, len2
);
1839 static HRESULT WINAPI
DS8Buffer_Restore(IDirectSoundBuffer8
*iface
)
1841 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1844 TRACE("(%p)->()\n", iface
);
1846 EnterCriticalSection(This
->crst
);
1847 if(This
->primary
->parent
->prio_level
< DSSCL_WRITEPRIMARY
||
1848 iface
== This
->primary
->write_emu
)
1850 This
->bufferlost
= 0;
1854 hr
= DSERR_BUFFERLOST
;
1855 LeaveCriticalSection(This
->crst
);
1860 static HRESULT WINAPI
DS8Buffer_SetFX(IDirectSoundBuffer8
*iface
, DWORD fxcount
, DSEFFECTDESC
*desc
, DWORD
*rescodes
)
1862 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1865 TRACE("(%p)->(%"LONGFMT
"u, %p, %p)\n", This
, fxcount
, desc
, rescodes
);
1867 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFX
))
1869 WARN("FX control not set\n");
1870 return DSERR_CONTROLUNAVAIL
;
1875 if(desc
|| rescodes
)
1877 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1878 return DSERR_INVALIDPARAM
;
1881 /* No effects; we can handle that */
1885 if(!desc
|| !rescodes
)
1887 WARN("NULL desc and/or result pointer specified.\n");
1888 return DSERR_INVALIDPARAM
;
1891 /* We don't (currently) handle DSound effects */
1892 for(i
= 0;i
< fxcount
;++i
)
1894 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc
[i
].guidDSFXClass
));
1895 rescodes
[i
] = DSFXR_FAILED
;
1898 return DS_INCOMPLETE
;
1901 static HRESULT WINAPI
DS8Buffer_AcquireResources(IDirectSoundBuffer8
*iface
, DWORD flags
, DWORD fxcount
, DWORD
*rescodes
)
1903 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1905 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %p)\n", This
, flags
, fxcount
, rescodes
);
1907 /* effects aren't supported at the moment.. */
1908 if(fxcount
!= 0 || rescodes
)
1910 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1911 return DSERR_INVALIDPARAM
;
1914 EnterCriticalSection(This
->crst
);
1915 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1917 This
->buffer
->dsbflags
&= ~(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
);
1918 if((flags
&DSBPLAY_LOCSOFTWARE
))
1919 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1921 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1923 LeaveCriticalSection(This
->crst
);
1928 static HRESULT WINAPI
DS8Buffer_GetObjectInPath(IDirectSoundBuffer8
*iface
, REFGUID guid
, DWORD idx
, REFGUID rguidiface
, void **ppv
)
1930 FIXME("(%p)->(%s, %"LONGFMT
"u, %s, %p) : stub!\n", iface
, debugstr_guid(guid
), idx
, debugstr_guid(rguidiface
), ppv
);
1934 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
= {
1935 DS8Buffer_QueryInterface
,
1939 DS8Buffer_GetCurrentPosition
,
1940 DS8Buffer_GetFormat
,
1941 DS8Buffer_GetVolume
,
1943 DS8Buffer_GetFrequency
,
1944 DS8Buffer_GetStatus
,
1945 DS8Buffer_Initialize
,
1948 DS8Buffer_SetCurrentPosition
,
1949 DS8Buffer_SetFormat
,
1950 DS8Buffer_SetVolume
,
1952 DS8Buffer_SetFrequency
,
1957 DS8Buffer_AcquireResources
,
1958 DS8Buffer_GetObjectInPath
1962 static HRESULT WINAPI
DSBuffer_QueryInterface(IDirectSoundBuffer
*iface
, REFIID riid
, void **ppv
)
1964 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1965 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
1968 static ULONG WINAPI
DSBuffer_AddRef(IDirectSoundBuffer
*iface
)
1970 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1971 return DS8Buffer_AddRef(&This
->IDirectSoundBuffer8_iface
);
1974 static ULONG WINAPI
DSBuffer_Release(IDirectSoundBuffer
*iface
)
1976 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1977 return DS8Buffer_Release(&This
->IDirectSoundBuffer8_iface
);
1980 static HRESULT WINAPI
DSBuffer_GetCaps(IDirectSoundBuffer
*iface
, DSBCAPS
*caps
)
1982 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1983 return DS8Buffer_GetCaps(&This
->IDirectSoundBuffer8_iface
, caps
);
1986 static HRESULT WINAPI
DSBuffer_GetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD
*playpos
, DWORD
*curpos
)
1988 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1989 return DS8Buffer_GetCurrentPosition(&This
->IDirectSoundBuffer8_iface
, playpos
, curpos
);
1992 static HRESULT WINAPI
DSBuffer_GetFormat(IDirectSoundBuffer
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
1994 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1995 return DS8Buffer_GetFormat(&This
->IDirectSoundBuffer8_iface
, wfx
, allocated
, written
);
1998 static HRESULT WINAPI
DSBuffer_GetVolume(IDirectSoundBuffer
*iface
, LONG
*vol
)
2000 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2001 return DS8Buffer_GetVolume(&This
->IDirectSoundBuffer8_iface
, vol
);
2004 static HRESULT WINAPI
DSBuffer_GetPan(IDirectSoundBuffer
*iface
, LONG
*pan
)
2006 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2007 return DS8Buffer_GetPan(&This
->IDirectSoundBuffer8_iface
, pan
);
2010 static HRESULT WINAPI
DSBuffer_GetFrequency(IDirectSoundBuffer
*iface
, DWORD
*freq
)
2012 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2013 return DS8Buffer_GetFrequency(&This
->IDirectSoundBuffer8_iface
, freq
);
2016 static HRESULT WINAPI
DSBuffer_GetStatus(IDirectSoundBuffer
*iface
, DWORD
*status
)
2018 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2019 return DS8Buffer_GetStatus(&This
->IDirectSoundBuffer8_iface
, status
);
2022 static HRESULT WINAPI
DSBuffer_Initialize(IDirectSoundBuffer
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
2024 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2025 return DS8Buffer_Initialize(&This
->IDirectSoundBuffer8_iface
, ds
, desc
);
2028 static HRESULT WINAPI
DSBuffer_Lock(IDirectSoundBuffer
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
2030 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2031 return DS8Buffer_Lock(&This
->IDirectSoundBuffer8_iface
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
2034 static HRESULT WINAPI
DSBuffer_Play(IDirectSoundBuffer
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
2036 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2037 return DS8Buffer_Play(&This
->IDirectSoundBuffer8_iface
, res1
, prio
, flags
);
2040 static HRESULT WINAPI
DSBuffer_SetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD pos
)
2042 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2043 return DS8Buffer_SetCurrentPosition(&This
->IDirectSoundBuffer8_iface
, pos
);
2046 static HRESULT WINAPI
DSBuffer_SetFormat(IDirectSoundBuffer
*iface
, const WAVEFORMATEX
*wfx
)
2048 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2049 return DS8Buffer_SetFormat(&This
->IDirectSoundBuffer8_iface
, wfx
);
2052 static HRESULT WINAPI
DSBuffer_SetVolume(IDirectSoundBuffer
*iface
, LONG vol
)
2054 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2055 return DS8Buffer_SetVolume(&This
->IDirectSoundBuffer8_iface
, vol
);
2058 static HRESULT WINAPI
DSBuffer_SetPan(IDirectSoundBuffer
*iface
, LONG pan
)
2060 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2061 return DS8Buffer_SetPan(&This
->IDirectSoundBuffer8_iface
, pan
);
2064 static HRESULT WINAPI
DSBuffer_SetFrequency(IDirectSoundBuffer
*iface
, DWORD freq
)
2066 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2067 return DS8Buffer_SetFrequency(&This
->IDirectSoundBuffer8_iface
, freq
);
2070 static HRESULT WINAPI
DSBuffer_Stop(IDirectSoundBuffer
*iface
)
2072 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2073 return DS8Buffer_Stop(&This
->IDirectSoundBuffer8_iface
);
2076 static HRESULT WINAPI
DSBuffer_Unlock(IDirectSoundBuffer
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
2078 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2079 return DS8Buffer_Unlock(&This
->IDirectSoundBuffer8_iface
, ptr1
, len1
, ptr2
, len2
);
2082 static HRESULT WINAPI
DSBuffer_Restore(IDirectSoundBuffer
*iface
)
2084 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2085 return DS8Buffer_Restore(&This
->IDirectSoundBuffer8_iface
);
2088 static const IDirectSoundBufferVtbl DSBuffer_Vtbl
= {
2089 DSBuffer_QueryInterface
,
2093 DSBuffer_GetCurrentPosition
,
2097 DSBuffer_GetFrequency
,
2099 DSBuffer_Initialize
,
2102 DSBuffer_SetCurrentPosition
,
2106 DSBuffer_SetFrequency
,
2113 static HRESULT WINAPI
DS8Buffer3D_QueryInterface(IDirectSound3DBuffer
*iface
, REFIID riid
, void **ppv
)
2115 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2116 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2119 static ULONG WINAPI
DS8Buffer3D_AddRef(IDirectSound3DBuffer
*iface
)
2121 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2124 InterlockedIncrement(&This
->all_ref
);
2125 ret
= InterlockedIncrement(&This
->ds3d_ref
);
2126 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2131 static ULONG WINAPI
DS8Buffer3D_Release(IDirectSound3DBuffer
*iface
)
2133 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2136 ret
= InterlockedDecrement(&This
->ds3d_ref
);
2137 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2138 if(InterlockedDecrement(&This
->all_ref
) == 0)
2139 DS8Buffer_Destroy(This
);
2144 static HRESULT WINAPI
DS8Buffer3D_GetAllParameters(IDirectSound3DBuffer
*iface
, DS3DBUFFER
*ds3dbuffer
)
2146 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2150 TRACE("%p\n", This
);
2152 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2154 WARN("Invalid parameters %p %"LONGFMT
"u\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2155 return DSERR_INVALIDPARAM
;
2157 ds3dbuf
.dwSize
= sizeof(ds3dbuf
);
2159 EnterCriticalSection(This
->crst
);
2160 setALContext(This
->ctx
);
2162 hr
= IDirectSound3DBuffer_GetPosition(iface
, &ds3dbuf
.vPosition
);
2164 hr
= IDirectSound3DBuffer_GetVelocity(iface
, &ds3dbuf
.vVelocity
);
2166 hr
= IDirectSound3DBuffer_GetConeAngles(iface
, &ds3dbuf
.dwInsideConeAngle
, &ds3dbuf
.dwOutsideConeAngle
);
2168 hr
= IDirectSound3DBuffer_GetConeOrientation(iface
, &ds3dbuf
.vConeOrientation
);
2170 hr
= IDirectSound3DBuffer_GetConeOutsideVolume(iface
, &ds3dbuf
.lConeOutsideVolume
);
2172 hr
= IDirectSound3DBuffer_GetMinDistance(iface
, &ds3dbuf
.flMinDistance
);
2174 hr
= IDirectSound3DBuffer_GetMaxDistance(iface
, &ds3dbuf
.flMaxDistance
);
2176 hr
= IDirectSound3DBuffer_GetMode(iface
, &ds3dbuf
.dwMode
);
2178 memcpy(ds3dbuffer
, &ds3dbuf
, sizeof(ds3dbuf
));
2181 LeaveCriticalSection(This
->crst
);
2186 static HRESULT WINAPI
DS8Buffer3D_GetConeAngles(IDirectSound3DBuffer
*iface
, DWORD
*pdwInsideConeAngle
, DWORD
*pdwOutsideConeAngle
)
2188 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2189 ALint inangle
, outangle
;
2191 TRACE("(%p)->(%p, %p)\n", This
, pdwInsideConeAngle
, pdwOutsideConeAngle
);
2192 if(!pdwInsideConeAngle
|| !pdwOutsideConeAngle
)
2194 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle
, pdwOutsideConeAngle
);
2195 return DSERR_INVALIDPARAM
;
2198 EnterCriticalSection(This
->crst
);
2199 setALContext(This
->ctx
);
2201 alGetSourcei(This
->source
, AL_CONE_INNER_ANGLE
, &inangle
);
2202 alGetSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, &outangle
);
2204 *pdwInsideConeAngle
= inangle
;
2205 *pdwOutsideConeAngle
= outangle
;
2208 LeaveCriticalSection(This
->crst
);
2213 static HRESULT WINAPI
DS8Buffer3D_GetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVECTOR
*orient
)
2215 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2218 TRACE("(%p)->(%p)\n", This
, orient
);
2221 WARN("Invalid pointer\n");
2222 return DSERR_INVALIDPARAM
;
2225 EnterCriticalSection(This
->crst
);
2226 setALContext(This
->ctx
);
2228 alGetSourcefv(This
->source
, AL_DIRECTION
, dir
);
2232 orient
->z
= -dir
[2];
2235 LeaveCriticalSection(This
->crst
);
2240 static HRESULT WINAPI
DS8Buffer3D_GetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG
*vol
)
2242 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2245 TRACE("(%p)->(%p)\n", This
, vol
);
2248 WARN("Invalid pointer\n");
2249 return DSERR_INVALIDPARAM
;
2252 EnterCriticalSection(This
->crst
);
2253 setALContext(This
->ctx
);
2255 alGetSourcef(This
->source
, AL_CONE_OUTER_GAIN
, &gain
);
2259 LeaveCriticalSection(This
->crst
);
2261 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
2265 static HRESULT WINAPI
DS8Buffer3D_GetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*maxdist
)
2267 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2270 TRACE("(%p)->(%p)\n", This
, maxdist
);
2273 WARN("Invalid pointer\n");
2274 return DSERR_INVALIDPARAM
;
2277 EnterCriticalSection(This
->crst
);
2278 setALContext(This
->ctx
);
2280 alGetSourcef(This
->source
, AL_MAX_DISTANCE
, &dist
);
2284 LeaveCriticalSection(This
->crst
);
2290 static HRESULT WINAPI
DS8Buffer3D_GetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*mindist
)
2292 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2295 TRACE("(%p)->(%p)\n", This
, mindist
);
2298 WARN("Invalid pointer\n");
2299 return DSERR_INVALIDPARAM
;
2302 EnterCriticalSection(This
->crst
);
2303 setALContext(This
->ctx
);
2305 alGetSourcef(This
->source
, AL_REFERENCE_DISTANCE
, &dist
);
2310 LeaveCriticalSection(This
->crst
);
2315 static HRESULT WINAPI
DS8Buffer3D_GetMode(IDirectSound3DBuffer
*iface
, DWORD
*mode
)
2317 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2319 TRACE("(%p)->(%p)\n", This
, mode
);
2322 WARN("Invalid pointer\n");
2323 return DSERR_INVALIDPARAM
;
2326 EnterCriticalSection(This
->crst
);
2327 *mode
= This
->ds3dmode
;
2328 LeaveCriticalSection(This
->crst
);
2333 static HRESULT WINAPI
DS8Buffer3D_GetPosition(IDirectSound3DBuffer
*iface
, D3DVECTOR
*pos
)
2335 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2338 TRACE("(%p)->(%p)\n", This
, pos
);
2341 WARN("Invalid pointer\n");
2342 return DSERR_INVALIDPARAM
;
2345 EnterCriticalSection(This
->crst
);
2346 setALContext(This
->ctx
);
2348 alGetSourcefv(This
->source
, AL_POSITION
, alpos
);
2355 LeaveCriticalSection(This
->crst
);
2360 static HRESULT WINAPI
DS8Buffer3D_GetVelocity(IDirectSound3DBuffer
*iface
, D3DVECTOR
*vel
)
2362 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2365 TRACE("(%p)->(%p)\n", This
, vel
);
2368 WARN("Invalid pointer\n");
2369 return DSERR_INVALIDPARAM
;
2372 EnterCriticalSection(This
->crst
);
2373 setALContext(This
->ctx
);
2375 alGetSourcefv(This
->source
, AL_VELOCITY
, alvel
);
2382 LeaveCriticalSection(This
->crst
);
2387 static HRESULT WINAPI
DS8Buffer3D_SetAllParameters(IDirectSound3DBuffer
*iface
, const DS3DBUFFER
*ds3dbuffer
, DWORD apply
)
2389 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2390 TRACE("(%p)->(%p, %"LONGFMT
"u)\n", This
, ds3dbuffer
, apply
);
2392 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2394 WARN("Invalid DS3DBUFFER (%p, %"LONGFMT
"u)\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2395 return DSERR_INVALIDPARAM
;
2398 if(ds3dbuffer
->dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2399 ds3dbuffer
->dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2401 WARN("Invalid cone angles (%"LONGFMT
"u, %"LONGFMT
"u)\n", ds3dbuffer
->dwInsideConeAngle
,
2402 ds3dbuffer
->dwOutsideConeAngle
);
2403 return DSERR_INVALIDPARAM
;
2406 if(ds3dbuffer
->lConeOutsideVolume
> DSBVOLUME_MAX
||
2407 ds3dbuffer
->lConeOutsideVolume
< DSBVOLUME_MIN
)
2409 WARN("Invalid cone outside volume (%"LONGFMT
"d)\n", ds3dbuffer
->lConeOutsideVolume
);
2410 return DSERR_INVALIDPARAM
;
2413 if(ds3dbuffer
->flMaxDistance
< 0.0f
)
2415 WARN("Invalid max distance (%f)\n", ds3dbuffer
->flMaxDistance
);
2416 return DSERR_INVALIDPARAM
;
2419 if(ds3dbuffer
->flMinDistance
< 0.0f
)
2421 WARN("Invalid min distance (%f)\n", ds3dbuffer
->flMinDistance
);
2422 return DSERR_INVALIDPARAM
;
2425 if(ds3dbuffer
->dwMode
!= DS3DMODE_NORMAL
&&
2426 ds3dbuffer
->dwMode
!= DS3DMODE_HEADRELATIVE
&&
2427 ds3dbuffer
->dwMode
!= DS3DMODE_DISABLE
)
2429 WARN("Invalid mode (%"LONGFMT
"u)\n", ds3dbuffer
->dwMode
);
2430 return DSERR_INVALIDPARAM
;
2433 EnterCriticalSection(This
->crst
);
2434 setALContext(This
->ctx
);
2435 IDirectSound3DBuffer_SetPosition(iface
, ds3dbuffer
->vPosition
.x
, ds3dbuffer
->vPosition
.y
, ds3dbuffer
->vPosition
.z
, apply
);
2436 IDirectSound3DBuffer_SetVelocity(iface
, ds3dbuffer
->vVelocity
.x
, ds3dbuffer
->vVelocity
.y
, ds3dbuffer
->vVelocity
.z
, apply
);
2437 IDirectSound3DBuffer_SetConeAngles(iface
, ds3dbuffer
->dwInsideConeAngle
, ds3dbuffer
->dwOutsideConeAngle
, apply
);
2438 IDirectSound3DBuffer_SetConeOrientation(iface
, ds3dbuffer
->vConeOrientation
.x
, ds3dbuffer
->vConeOrientation
.y
, ds3dbuffer
->vConeOrientation
.z
, apply
);
2439 IDirectSound3DBuffer_SetConeOutsideVolume(iface
, ds3dbuffer
->lConeOutsideVolume
, apply
);
2440 IDirectSound3DBuffer_SetMinDistance(iface
, ds3dbuffer
->flMinDistance
, apply
);
2441 IDirectSound3DBuffer_SetMaxDistance(iface
, ds3dbuffer
->flMaxDistance
, apply
);
2442 IDirectSound3DBuffer_SetMode(iface
, ds3dbuffer
->dwMode
, apply
);
2444 LeaveCriticalSection(This
->crst
);
2449 static HRESULT WINAPI
DS8Buffer3D_SetConeAngles(IDirectSound3DBuffer
*iface
, DWORD dwInsideConeAngle
, DWORD dwOutsideConeAngle
, DWORD apply
)
2451 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2453 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %"LONGFMT
"u)\n", This
, dwInsideConeAngle
, dwOutsideConeAngle
, apply
);
2454 if(dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2455 dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2457 WARN("Invalid cone angles (%"LONGFMT
"u, %"LONGFMT
"u)\n", dwInsideConeAngle
, dwOutsideConeAngle
);
2458 return DSERR_INVALIDPARAM
;
2461 EnterCriticalSection(This
->crst
);
2462 if(apply
== DS3D_DEFERRED
)
2464 This
->ds3dbuffer
.dwInsideConeAngle
= dwInsideConeAngle
;
2465 This
->ds3dbuffer
.dwOutsideConeAngle
= dwOutsideConeAngle
;
2466 This
->dirty
.bit
.cone_angles
= 1;
2470 setALContext(This
->ctx
);
2471 alSourcei(This
->source
, AL_CONE_INNER_ANGLE
, dwInsideConeAngle
);
2472 alSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, dwOutsideConeAngle
);
2476 LeaveCriticalSection(This
->crst
);
2481 static HRESULT WINAPI
DS8Buffer3D_SetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2483 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2485 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", This
, x
, y
, z
, apply
);
2487 EnterCriticalSection(This
->crst
);
2488 if(apply
== DS3D_DEFERRED
)
2490 This
->ds3dbuffer
.vConeOrientation
.x
= x
;
2491 This
->ds3dbuffer
.vConeOrientation
.y
= y
;
2492 This
->ds3dbuffer
.vConeOrientation
.z
= z
;
2493 This
->dirty
.bit
.cone_orient
= 1;
2497 setALContext(This
->ctx
);
2498 alSource3f(This
->source
, AL_DIRECTION
, x
, y
, -z
);
2502 LeaveCriticalSection(This
->crst
);
2507 static HRESULT WINAPI
DS8Buffer3D_SetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG vol
, DWORD apply
)
2509 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2511 TRACE("(%p)->(%"LONGFMT
"d, %"LONGFMT
"u)\n", This
, vol
, apply
);
2512 if(vol
< DSBVOLUME_MIN
|| vol
> DSBVOLUME_MAX
)
2514 WARN("Invalid volume (%"LONGFMT
"d)\n", vol
);
2515 return DSERR_INVALIDPARAM
;
2518 EnterCriticalSection(This
->crst
);
2519 if(apply
== DS3D_DEFERRED
)
2521 This
->ds3dbuffer
.lConeOutsideVolume
= vol
;
2522 This
->dirty
.bit
.cone_outsidevolume
= 1;
2526 setALContext(This
->ctx
);
2527 alSourcef(This
->source
, AL_CONE_OUTER_GAIN
, mB_to_gain(vol
));
2531 LeaveCriticalSection(This
->crst
);
2536 static HRESULT WINAPI
DS8Buffer3D_SetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE maxdist
, DWORD apply
)
2538 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2540 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", This
, maxdist
, apply
);
2543 WARN("Invalid max distance (%f)\n", maxdist
);
2544 return DSERR_INVALIDPARAM
;
2547 EnterCriticalSection(This
->crst
);
2548 if(apply
== DS3D_DEFERRED
)
2550 This
->ds3dbuffer
.flMaxDistance
= maxdist
;
2551 This
->dirty
.bit
.max_distance
= 1;
2555 setALContext(This
->ctx
);
2556 alSourcef(This
->source
, AL_MAX_DISTANCE
, maxdist
);
2560 LeaveCriticalSection(This
->crst
);
2565 static HRESULT WINAPI
DS8Buffer3D_SetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE mindist
, DWORD apply
)
2567 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2569 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", This
, mindist
, apply
);
2572 WARN("Invalid min distance (%f)\n", mindist
);
2573 return DSERR_INVALIDPARAM
;
2576 EnterCriticalSection(This
->crst
);
2577 if(apply
== DS3D_DEFERRED
)
2579 This
->ds3dbuffer
.flMinDistance
= mindist
;
2580 This
->dirty
.bit
.min_distance
= 1;
2584 setALContext(This
->ctx
);
2585 alSourcef(This
->source
, AL_REFERENCE_DISTANCE
, mindist
);
2589 LeaveCriticalSection(This
->crst
);
2594 static HRESULT WINAPI
DS8Buffer3D_SetMode(IDirectSound3DBuffer
*iface
, DWORD mode
, DWORD apply
)
2596 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2598 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u)\n", This
, mode
, apply
);
2599 if(mode
!= DS3DMODE_NORMAL
&& mode
!= DS3DMODE_HEADRELATIVE
&&
2600 mode
!= DS3DMODE_DISABLE
)
2602 WARN("Invalid mode (%"LONGFMT
"u)\n", mode
);
2603 return DSERR_INVALIDPARAM
;
2606 EnterCriticalSection(This
->crst
);
2607 if(apply
== DS3D_DEFERRED
)
2609 This
->ds3dbuffer
.dwMode
= mode
;
2610 This
->dirty
.bit
.mode
= 1;
2614 setALContext(This
->ctx
);
2615 alSourcei(This
->source
, AL_SOURCE_RELATIVE
,
2616 (mode
!= DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
2617 alSourcef(This
->source
, AL_ROLLOFF_FACTOR
,
2618 (mode
== DS3DMODE_DISABLE
) ? 0.0f
: This
->primary
->rollofffactor
);
2619 This
->ds3dmode
= mode
;
2623 LeaveCriticalSection(This
->crst
);
2628 static HRESULT WINAPI
DS8Buffer3D_SetPosition(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2630 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2632 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", This
, x
, y
, z
, apply
);
2634 EnterCriticalSection(This
->crst
);
2635 if(apply
== DS3D_DEFERRED
)
2637 This
->ds3dbuffer
.vPosition
.x
= x
;
2638 This
->ds3dbuffer
.vPosition
.y
= y
;
2639 This
->ds3dbuffer
.vPosition
.z
= z
;
2640 This
->dirty
.bit
.pos
= 1;
2644 setALContext(This
->ctx
);
2645 alSource3f(This
->source
, AL_POSITION
, x
, y
, -z
);
2649 LeaveCriticalSection(This
->crst
);
2654 static HRESULT WINAPI
DS8Buffer3D_SetVelocity(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2656 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2658 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", This
, x
, y
, z
, apply
);
2660 EnterCriticalSection(This
->crst
);
2661 if(apply
== DS3D_DEFERRED
)
2663 This
->ds3dbuffer
.vVelocity
.x
= x
;
2664 This
->ds3dbuffer
.vVelocity
.y
= y
;
2665 This
->ds3dbuffer
.vVelocity
.z
= z
;
2666 This
->dirty
.bit
.vel
= 1;
2670 setALContext(This
->ctx
);
2671 alSource3f(This
->source
, AL_VELOCITY
, x
, y
, -z
);
2675 LeaveCriticalSection(This
->crst
);
2680 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
=
2682 DS8Buffer3D_QueryInterface
,
2684 DS8Buffer3D_Release
,
2685 DS8Buffer3D_GetAllParameters
,
2686 DS8Buffer3D_GetConeAngles
,
2687 DS8Buffer3D_GetConeOrientation
,
2688 DS8Buffer3D_GetConeOutsideVolume
,
2689 DS8Buffer3D_GetMaxDistance
,
2690 DS8Buffer3D_GetMinDistance
,
2691 DS8Buffer3D_GetMode
,
2692 DS8Buffer3D_GetPosition
,
2693 DS8Buffer3D_GetVelocity
,
2694 DS8Buffer3D_SetAllParameters
,
2695 DS8Buffer3D_SetConeAngles
,
2696 DS8Buffer3D_SetConeOrientation
,
2697 DS8Buffer3D_SetConeOutsideVolume
,
2698 DS8Buffer3D_SetMaxDistance
,
2699 DS8Buffer3D_SetMinDistance
,
2700 DS8Buffer3D_SetMode
,
2701 DS8Buffer3D_SetPosition
,
2702 DS8Buffer3D_SetVelocity
2706 static HRESULT WINAPI
DS8BufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
2708 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2709 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2712 static ULONG WINAPI
DS8BufferNot_AddRef(IDirectSoundNotify
*iface
)
2714 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2717 InterlockedIncrement(&This
->all_ref
);
2718 ret
= InterlockedIncrement(&This
->not_ref
);
2719 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2724 static ULONG WINAPI
DS8BufferNot_Release(IDirectSoundNotify
*iface
)
2726 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2729 ret
= InterlockedDecrement(&This
->not_ref
);
2730 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2731 if(InterlockedDecrement(&This
->all_ref
) == 0)
2732 DS8Buffer_Destroy(This
);
2737 static HRESULT WINAPI
DS8BufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
2739 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2740 DSBPOSITIONNOTIFY
*nots
;
2744 EnterCriticalSection(This
->crst
);
2745 hr
= DSERR_INVALIDPARAM
;
2746 if(count
&& !notifications
)
2749 hr
= IDirectSoundBuffer8_GetStatus(&This
->IDirectSoundBuffer8_iface
, &state
);
2753 hr
= DSERR_INVALIDCALL
;
2754 if((state
&DSBSTATUS_PLAYING
))
2759 HeapFree(GetProcessHeap(), 0, This
->notify
);
2768 hr
= DSERR_INVALIDPARAM
;
2769 for(i
= 0;i
< count
;++i
)
2771 if(notifications
[i
].dwOffset
>= This
->buffer
->buf_size
&&
2772 notifications
[i
].dwOffset
!= (DWORD
)DSBPN_OFFSETSTOP
)
2777 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
2780 memcpy(nots
, notifications
, count
*sizeof(*nots
));
2782 HeapFree(GetProcessHeap(), 0, This
->notify
);
2783 This
->notify
= nots
;
2784 This
->nnotify
= count
;
2790 LeaveCriticalSection(This
->crst
);
2794 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
=
2796 DS8BufferNot_QueryInterface
,
2797 DS8BufferNot_AddRef
,
2798 DS8BufferNot_Release
,
2799 DS8BufferNot_SetNotificationPositions
2803 static HRESULT WINAPI
DS8BufferProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
2805 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2806 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2809 static ULONG WINAPI
DS8BufferProp_AddRef(IKsPropertySet
*iface
)
2811 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2814 InterlockedIncrement(&This
->all_ref
);
2815 ret
= InterlockedIncrement(&This
->prop_ref
);
2816 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2821 static ULONG WINAPI
DS8BufferProp_Release(IKsPropertySet
*iface
)
2823 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2826 ret
= InterlockedDecrement(&This
->prop_ref
);
2827 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2828 if(InterlockedDecrement(&This
->all_ref
) == 0)
2829 DS8Buffer_Destroy(This
);
2834 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2835 handled through secondary buffers. */
2836 static HRESULT WINAPI
DS8BufferProp_Get(IKsPropertySet
*iface
,
2837 REFGUID guidPropSet
, ULONG dwPropID
,
2838 LPVOID pInstanceData
, ULONG cbInstanceData
,
2839 LPVOID pPropData
, ULONG cbPropData
,
2842 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2843 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2845 TRACE("(%p)->(%s, %"LONGFMT
"u, %p, %"LONGFMT
"u, %p, %"LONGFMT
"u, %p)\n", iface
, debugstr_guid(guidPropSet
),
2846 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
2853 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2859 /* Not a known buffer/source property. Pass it to the listener */
2860 hr
= IKsPropertySet_Get(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2861 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
,
2868 static HRESULT WINAPI
DS8BufferProp_Set(IKsPropertySet
*iface
,
2869 REFGUID guidPropSet
, ULONG dwPropID
,
2870 LPVOID pInstanceData
, ULONG cbInstanceData
,
2871 LPVOID pPropData
, ULONG cbPropData
)
2873 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2874 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2876 TRACE("(%p)->(%s, %"LONGFMT
"u, %p, %"LONGFMT
"u, %p, %"LONGFMT
"u)\n", iface
, debugstr_guid(guidPropSet
),
2877 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
2880 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2886 /* Not a known buffer/source property. Pass it to the listener */
2887 hr
= IKsPropertySet_Set(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2888 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
,
2895 static HRESULT WINAPI
DS8BufferProp_QuerySupport(IKsPropertySet
*iface
,
2896 REFGUID guidPropSet
, ULONG dwPropID
,
2897 PULONG pTypeSupport
)
2899 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2900 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2902 TRACE("(%p)->(%s, %"LONGFMT
"u, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
2909 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2915 /* Not a known buffer/source property. Pass it to the listener */
2916 hr
= IKsPropertySet_QuerySupport(&This
->primary
->IKsPropertySet_iface
,
2917 guidPropSet
, dwPropID
, pTypeSupport
);
2923 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
=
2925 DS8BufferProp_QueryInterface
,
2926 DS8BufferProp_AddRef
,
2927 DS8BufferProp_Release
,
2930 DS8BufferProp_QuerySupport