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 /* Should be called with critsect held and context set.. */
112 static void DS8Buffer_addnotify(DS8Buffer
*buf
)
117 list
= buf
->primary
->notifies
;
118 for(i
= 0; i
< buf
->primary
->nnotifies
; ++i
)
122 ERR("Buffer %p already in notification list\n", buf
);
126 if(buf
->primary
->nnotifies
== buf
->primary
->sizenotifies
)
128 list
= HeapReAlloc(GetProcessHeap(), 0, list
, (buf
->primary
->nnotifies
+ 1) * sizeof(*list
));
131 buf
->primary
->sizenotifies
++;
133 list
[buf
->primary
->nnotifies
++] = buf
;
134 buf
->primary
->notifies
= list
;
138 static const char *get_fmtstr_PCM(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
140 out
->Format
= *format
;
141 out
->Format
.cbSize
= 0;
143 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
144 !prim
->SupportedExt
[EXT_MCFORMATS
])
146 WARN("Multi-channel not available\n");
150 if(format
->wBitsPerSample
== 8)
152 switch(format
->nChannels
)
154 case 1: return "AL_FORMAT_MONO8";
155 case 2: return "AL_FORMAT_STEREO8";
156 case 4: return "AL_FORMAT_QUAD8";
157 case 6: return "AL_FORMAT_51CHN8";
158 case 7: return "AL_FORMAT_61CHN8";
159 case 8: return "AL_FORMAT_71CHN8";
162 else if(format
->wBitsPerSample
== 16)
164 switch(format
->nChannels
)
166 case 1: return "AL_FORMAT_MONO16";
167 case 2: return "AL_FORMAT_STEREO16";
168 case 4: return "AL_FORMAT_QUAD16";
169 case 6: return "AL_FORMAT_51CHN16";
170 case 7: return "AL_FORMAT_61CHN16";
171 case 8: return "AL_FORMAT_71CHN16";
175 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
176 format
->wBitsPerSample
, format
->nChannels
);
179 static ALenum
get_fmt_PCM(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
181 out
->Format
= *format
;
182 out
->Format
.cbSize
= 0;
184 if(format
->wBitsPerSample
== 8)
186 *in_type
= AL_UNSIGNED_BYTE
;
187 switch(format
->nChannels
)
189 case 1: *in_chans
= AL_MONO
;
191 case 2: *in_chans
= AL_STEREO
;
193 case 4: *in_chans
= AL_QUAD
;
195 case 6: *in_chans
= AL_5POINT1
;
197 case 7: *in_chans
= AL_6POINT1
;
199 case 8: *in_chans
= AL_7POINT1
;
203 else if(format
->wBitsPerSample
== 16)
206 switch(format
->nChannels
)
208 case 1: *in_chans
= AL_MONO
;
210 case 2: *in_chans
= AL_STEREO
;
212 case 4: *in_chans
= AL_QUAD
;
214 case 6: *in_chans
= AL_5POINT1
;
215 return AL_5POINT1_16
;
216 case 7: *in_chans
= AL_6POINT1
;
217 return AL_6POINT1_16
;
218 case 8: *in_chans
= AL_7POINT1
;
219 return AL_7POINT1_16
;
222 #if 0 /* Will cause incorrect byte offsets */
223 else if(format
->wBitsPerSample
== 24)
226 switch(format
->nChannels
)
228 case 1: *in_chans
= AL_MONO
;
230 case 2: *in_chans
= AL_STEREO
;
232 case 4: *in_chans
= AL_QUAD
;
234 case 6: *in_chans
= AL_5POINT1
;
235 return AL_5POINT1_32F
;
236 case 7: *in_chans
= AL_6POINT1
;
237 return AL_6POINT1_32F
;
238 case 8: *in_chans
= AL_7POINT1
;
239 return AL_7POINT1_32F
;
243 else if(format
->wBitsPerSample
== 32)
246 switch(format
->nChannels
)
248 case 1: *in_chans
= AL_MONO
;
250 case 2: *in_chans
= AL_STEREO
;
252 case 4: *in_chans
= AL_QUAD
;
254 case 6: *in_chans
= AL_5POINT1
;
255 return AL_5POINT1_32F
;
256 case 7: *in_chans
= AL_6POINT1
;
257 return AL_6POINT1_32F
;
258 case 8: *in_chans
= AL_7POINT1
;
259 return AL_7POINT1_32F
;
263 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
264 format
->wBitsPerSample
, format
->nChannels
);
268 static const char *get_fmtstr_FLOAT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
270 out
->Format
= *format
;
271 out
->Format
.cbSize
= 0;
273 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
274 !prim
->SupportedExt
[EXT_MCFORMATS
])
276 WARN("Multi-channel not available\n");
280 if(format
->wBitsPerSample
== 32 && prim
->SupportedExt
[EXT_FLOAT32
])
282 switch(format
->nChannels
)
284 case 1: return "AL_FORMAT_MONO_FLOAT32";
285 case 2: return "AL_FORMAT_STEREO_FLOAT32";
286 case 4: return "AL_FORMAT_QUAD32";
287 case 6: return "AL_FORMAT_51CHN32";
288 case 7: return "AL_FORMAT_61CHN32";
289 case 8: return "AL_FORMAT_71CHN32";
293 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
294 format
->wBitsPerSample
, format
->nChannels
);
297 static ALenum
get_fmt_FLOAT(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
299 out
->Format
= *format
;
300 out
->Format
.cbSize
= 0;
302 if(format
->wBitsPerSample
== 32)
305 switch(format
->nChannels
)
307 case 1: *in_chans
= AL_MONO
;
309 case 2: *in_chans
= AL_STEREO
;
311 case 4: *in_chans
= AL_QUAD
;
313 case 6: *in_chans
= AL_5POINT1
;
314 return AL_5POINT1_32F
;
315 case 7: *in_chans
= AL_6POINT1
;
316 return AL_6POINT1_32F
;
317 case 8: *in_chans
= AL_7POINT1
;
318 return AL_7POINT1_32F
;
321 #if 0 /* Will cause incorrect byte offsets */
322 else if(format
->wBitsPerSample
== 64)
324 *in_type
= AL_DOUBLE
;
325 switch(format
->nChannels
)
327 case 1: *in_chans
= AL_MONO
;
329 case 2: *in_chans
= AL_STEREO
;
331 case 4: *in_chans
= AL_QUAD
;
333 case 6: *in_chans
= AL_5POINT1
;
334 return AL_5POINT1_32F
;
335 case 7: *in_chans
= AL_6POINT1
;
336 return AL_6POINT1_32F
;
337 case 8: *in_chans
= AL_7POINT1
;
338 return AL_7POINT1_32F
;
343 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
344 format
->wBitsPerSample
, format
->nChannels
);
348 /* Speaker configs */
349 #define MONO SPEAKER_FRONT_CENTER
350 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
351 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
352 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
353 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
354 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
355 #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)
357 static const char *get_fmtstr_EXT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
359 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
360 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
362 if(!out
->Samples
.wValidBitsPerSample
)
363 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
364 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
366 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
370 if(out
->dwChannelMask
!= MONO
&& out
->dwChannelMask
!= STEREO
&&
371 !prim
->SupportedExt
[EXT_MCFORMATS
])
373 WARN("Multi-channel not available\n");
377 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
379 if(out
->Samples
.wValidBitsPerSample
== 8)
381 switch(out
->dwChannelMask
)
383 case MONO
: return "AL_FORMAT_MONO8";
384 case STEREO
: return "AL_FORMAT_STEREO8";
385 case REAR
: return "AL_FORMAT_REAR8";
386 case QUAD
: return "AL_FORMAT_QUAD8";
387 case X5DOT1
: return "AL_FORMAT_51CHN8";
388 case X6DOT1
: return "AL_FORMAT_61CHN8";
389 case X7DOT1
: return "AL_FORMAT_71CHN8";
392 else if(out
->Samples
.wValidBitsPerSample
== 16)
394 switch(out
->dwChannelMask
)
396 case MONO
: return "AL_FORMAT_MONO16";
397 case STEREO
: return "AL_FORMAT_STEREO16";
398 case REAR
: return "AL_FORMAT_REAR16";
399 case QUAD
: return "AL_FORMAT_QUAD16";
400 case X5DOT1
: return "AL_FORMAT_51CHN16";
401 case X6DOT1
: return "AL_FORMAT_61CHN16";
402 case X7DOT1
: return "AL_FORMAT_71CHN16";
406 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#"LONGFMT
"x)\n",
407 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
410 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
411 prim
->SupportedExt
[EXT_FLOAT32
])
413 if(out
->Samples
.wValidBitsPerSample
== 32)
415 switch(out
->dwChannelMask
)
417 case MONO
: return "AL_FORMAT_MONO_FLOAT32";
418 case STEREO
: return "AL_FORMAT_STEREO_FLOAT32";
419 case REAR
: return "AL_FORMAT_REAR32";
420 case QUAD
: return "AL_FORMAT_QUAD32";
421 case X5DOT1
: return "AL_FORMAT_51CHN32";
422 case X6DOT1
: return "AL_FORMAT_61CHN32";
423 case X7DOT1
: return "AL_FORMAT_71CHN32";
428 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
432 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#"LONGFMT
"x)\n",
433 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
436 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
437 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
440 static ALenum
get_fmt_EXT(const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
442 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
443 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
445 if(!out
->Samples
.wValidBitsPerSample
)
446 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
447 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
449 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
453 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
455 if(out
->Samples
.wValidBitsPerSample
== 8)
457 *in_type
= AL_UNSIGNED_BYTE
;
458 switch(out
->dwChannelMask
)
460 case MONO
: *in_chans
= AL_MONO
;
462 case STEREO
: *in_chans
= AL_STEREO
;
464 case REAR
: *in_chans
= AL_REAR
;
466 case QUAD
: *in_chans
= AL_QUAD
;
468 case X5DOT1
: *in_chans
= AL_5POINT1
;
470 case X6DOT1
: *in_chans
= AL_6POINT1
;
472 case X7DOT1
: *in_chans
= AL_7POINT1
;
476 else if(out
->Samples
.wValidBitsPerSample
== 16)
479 switch(out
->dwChannelMask
)
481 case MONO
: *in_chans
= AL_MONO
;
483 case STEREO
: *in_chans
= AL_STEREO
;
485 case REAR
: *in_chans
= AL_REAR
;
487 case QUAD
: *in_chans
= AL_QUAD
;
489 case X5DOT1
: *in_chans
= AL_5POINT1
;
490 return AL_5POINT1_16
;
491 case X6DOT1
: *in_chans
= AL_6POINT1
;
492 return AL_6POINT1_16
;
493 case X7DOT1
: *in_chans
= AL_7POINT1
;
494 return AL_7POINT1_16
;
498 else if(out
->Samples
.wValidBitsPerSample
== 24)
501 switch(out
->dwChannelMask
)
503 case MONO
: *in_chans
= AL_MONO
;
505 case STEREO
: *in_chans
= AL_STEREO
;
507 case REAR
: *in_chans
= AL_REAR
;
509 case QUAD
: *in_chans
= AL_QUAD
;
511 case X5DOT1
: *in_chans
= AL_5POINT1
;
512 return AL_5POINT1_32F
;
513 case X6DOT1
: *in_chans
= AL_6POINT1
;
514 return AL_6POINT1_32F
;
515 case X7DOT1
: *in_chans
= AL_7POINT1
;
516 return AL_7POINT1_32F
;
520 else if(out
->Samples
.wValidBitsPerSample
== 32)
523 switch(out
->dwChannelMask
)
525 case MONO
: *in_chans
= AL_MONO
;
527 case STEREO
: *in_chans
= AL_STEREO
;
529 case REAR
: *in_chans
= AL_REAR
;
531 case QUAD
: *in_chans
= AL_QUAD
;
533 case X5DOT1
: *in_chans
= AL_5POINT1
;
534 return AL_5POINT1_32F
;
535 case X6DOT1
: *in_chans
= AL_6POINT1
;
536 return AL_6POINT1_32F
;
537 case X7DOT1
: *in_chans
= AL_7POINT1
;
538 return AL_7POINT1_32F
;
542 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#"LONGFMT
"x)\n",
543 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
546 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))
548 if(out
->Samples
.wValidBitsPerSample
== 32)
551 switch(out
->dwChannelMask
)
553 case MONO
: *in_chans
= AL_MONO
;
555 case STEREO
: *in_chans
= AL_STEREO
;
557 case REAR
: *in_chans
= AL_REAR
;
559 case QUAD
: *in_chans
= AL_QUAD
;
561 case X5DOT1
: *in_chans
= AL_5POINT1
;
562 return AL_5POINT1_32F
;
563 case X6DOT1
: *in_chans
= AL_6POINT1
;
564 return AL_6POINT1_32F
;
565 case X7DOT1
: *in_chans
= AL_7POINT1
;
566 return AL_7POINT1_32F
;
570 else if(out
->Samples
.wValidBitsPerSample
== 64)
572 *in_type
= AL_DOUBLE
;
573 switch(out
->dwChannelMask
)
575 case MONO
: *in_chans
= AL_MONO
;
577 case STEREO
: *in_chans
= AL_STEREO
;
579 case REAR
: *in_chans
= AL_REAR
;
581 case QUAD
: *in_chans
= AL_QUAD
;
583 case X5DOT1
: *in_chans
= AL_5POINT1
;
584 return AL_5POINT1_32F
;
585 case X6DOT1
: *in_chans
= AL_6POINT1
;
586 return AL_6POINT1_32F
;
587 case X7DOT1
: *in_chans
= AL_7POINT1
;
588 return AL_7POINT1_32F
;
594 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
598 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#"LONGFMT
"x)\n",
599 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
602 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
603 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
607 static void DS8Data_Release(DS8Data
*This
);
608 static HRESULT
DS8Data_Create(DS8Data
**ppv
, const DSBUFFERDESC
*desc
, DS8Primary
*prim
)
610 HRESULT hr
= DSERR_INVALIDPARAM
;
611 const WAVEFORMATEX
*format
;
614 format
= desc
->lpwfxFormat
;
615 TRACE("Requested buffer format:\n"
616 " FormatTag = 0x%04x\n"
618 " SamplesPerSec = %"LONGFMT
"u\n"
619 " AvgBytesPerSec = %"LONGFMT
"u\n"
621 " BitsPerSample = %d\n",
622 format
->wFormatTag
, format
->nChannels
,
623 format
->nSamplesPerSec
, format
->nAvgBytesPerSec
,
624 format
->nBlockAlign
, format
->wBitsPerSample
);
626 if(format
->nBlockAlign
== 0)
628 WARN("Invalid BlockAlign specified\n");
629 return DSERR_INVALIDPARAM
;
632 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
633 * will need the EAX-RAM extension. Currently, we just tell the app it
634 * gets what it wanted. */
635 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
));
637 return E_OUTOFMEMORY
;
640 pBuffer
->dsbflags
= desc
->dwFlags
;
641 if((pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
)) == (DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
))
643 WARN("Hardware and software location requested\n");
646 if(!(pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCDEFER
)))
647 pBuffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
649 pBuffer
->buf_size
= desc
->dwBufferBytes
+ format
->nBlockAlign
- 1;
650 pBuffer
->buf_size
-= pBuffer
->buf_size
%format
->nBlockAlign
;
652 hr
= DSERR_BUFFERTOOSMALL
;
653 if(pBuffer
->buf_size
< DSBSIZE_MIN
)
656 hr
= DSERR_INVALIDPARAM
;
657 if(pBuffer
->buf_size
> DSBSIZE_MAX
)
660 pBuffer
->numsegs
= 1;
661 pBuffer
->segsize
= pBuffer
->buf_size
;
662 pBuffer
->lastsegsize
= pBuffer
->buf_size
;
664 if(!prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
666 const char *fmt_str
= NULL
;
668 if(!(pBuffer
->dsbflags
&DSBCAPS_STATIC
) &&
669 !prim
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] &&
670 !prim
->SupportedExt
[EXT_STATIC_BUFFER
])
672 ALCint refresh
= FAKE_REFRESH_COUNT
;
675 alcGetIntegerv(prim
->parent
->device
, ALC_REFRESH
, 1, &refresh
);
676 checkALCError(prim
->parent
->device
);
678 newSize
= format
->nAvgBytesPerSec
/refresh
+ format
->nBlockAlign
- 1;
679 newSize
-= newSize
%format
->nBlockAlign
;
681 /* Make sure enough buffers are available */
682 if(newSize
> pBuffer
->buf_size
/(QBUFFERS
+2))
683 ERR("Buffer segments too large to stream (%u for %u)!\n",
684 newSize
, pBuffer
->buf_size
);
687 pBuffer
->numsegs
= pBuffer
->buf_size
/newSize
;
688 pBuffer
->segsize
= newSize
;
689 pBuffer
->lastsegsize
= pBuffer
->buf_size
- (newSize
*(pBuffer
->numsegs
-1));
690 TRACE("New streaming buffer (%u chunks, %u : %u sizes)\n",
691 pBuffer
->numsegs
, pBuffer
->segsize
, pBuffer
->lastsegsize
);
695 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
696 fmt_str
= get_fmtstr_PCM(prim
, format
, &pBuffer
->format
);
697 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
698 fmt_str
= get_fmtstr_FLOAT(prim
, format
, &pBuffer
->format
);
699 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
701 const WAVEFORMATEXTENSIBLE
*wfe
;
703 hr
= DSERR_CONTROLUNAVAIL
;
704 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
705 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
708 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
709 TRACE("Extensible values:\n"
711 " ChannelMask = 0x%"LONGFMT
"x\n"
713 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
714 debugstr_guid(&wfe
->SubFormat
));
716 fmt_str
= get_fmtstr_EXT(prim
, format
, &pBuffer
->format
);
719 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
721 hr
= DSERR_INVALIDCALL
;
725 pBuffer
->buf_format
= alGetEnumValue(fmt_str
);
726 if(alGetError() != AL_NO_ERROR
|| pBuffer
->buf_format
== 0 ||
727 pBuffer
->buf_format
== -1)
729 WARN("Could not get OpenAL format from %s\n", fmt_str
);
735 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
736 pBuffer
->buf_format
= get_fmt_PCM(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
737 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
738 pBuffer
->buf_format
= get_fmt_FLOAT(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
739 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
741 const WAVEFORMATEXTENSIBLE
*wfe
;
743 hr
= DSERR_CONTROLUNAVAIL
;
744 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
745 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
748 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
749 TRACE("Extensible values:\n"
751 " ChannelMask = 0x%"LONGFMT
"x\n"
753 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
754 debugstr_guid(&wfe
->SubFormat
));
756 pBuffer
->buf_format
= get_fmt_EXT(format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
759 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
761 hr
= DSERR_INVALIDCALL
;
762 if(prim
->ExtAL
->IsBufferFormatSupportedSOFT(pBuffer
->buf_format
) == AL_FALSE
)
764 WARN("Unsupported OpenAL format: 0x%x\n", pBuffer
->buf_format
);
770 pBuffer
->buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
->buffers
)*pBuffer
->numsegs
);
771 pBuffer
->data
= HeapAlloc(GetProcessHeap(), 0, pBuffer
->buf_size
);
772 if(!pBuffer
->buffers
|| !pBuffer
->data
)
775 alGenBuffers(pBuffer
->numsegs
, pBuffer
->buffers
);
782 DS8Data_Release(pBuffer
);
786 static void DS8Data_AddRef(DS8Data
*data
)
788 InterlockedIncrement(&data
->ref
);
791 /* This function is always called with the device lock held */
792 static void DS8Data_Release(DS8Data
*This
)
794 if(InterlockedDecrement(&This
->ref
)) return;
796 TRACE("Deleting %p\n", This
);
797 if (This
->buffers
&& This
->buffers
[0])
799 alDeleteBuffers(This
->numsegs
, This
->buffers
);
802 HeapFree(GetProcessHeap(), 0, This
->buffers
);
803 HeapFree(GetProcessHeap(), 0, This
->data
);
804 HeapFree(GetProcessHeap(), 0, This
);
807 HRESULT
DS8Buffer_Create(DS8Buffer
**ppv
, DS8Primary
*prim
, IDirectSoundBuffer
*orig
)
813 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
814 if(!This
) return DSERR_OUTOFMEMORY
;
816 This
->IDirectSoundBuffer8_iface
.lpVtbl
= (IDirectSoundBuffer8Vtbl
*)&DS8Buffer_Vtbl
;
817 This
->IDirectSoundBuffer_iface
.lpVtbl
= (IDirectSoundBufferVtbl
*)&DSBuffer_Vtbl
;
818 This
->IDirectSound3DBuffer_iface
.lpVtbl
= (IDirectSound3DBufferVtbl
*)&DS8Buffer3d_Vtbl
;
819 This
->IDirectSoundNotify_iface
.lpVtbl
= (IDirectSoundNotifyVtbl
*)&DS8BufferNot_Vtbl
;
820 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8BufferProp_Vtbl
;
822 This
->primary
= prim
;
823 This
->ctx
= prim
->ctx
;
824 This
->ExtAL
= prim
->ExtAL
;
825 This
->crst
= prim
->crst
;
826 This
->ref
= This
->all_ref
= 1;
830 DS8Buffer
*org
= impl_from_IDirectSoundBuffer(orig
);
831 hr
= DSERR_BUFFERLOST
;
834 DS8Data_AddRef(org
->buffer
);
835 This
->buffer
= org
->buffer
;
838 /* Append to buffer list */
839 if(prim
->nbuffers
== prim
->sizebuffers
)
843 hr
= DSERR_OUTOFMEMORY
;
844 bufs
= HeapReAlloc(GetProcessHeap(), 0, prim
->buffers
, sizeof(*bufs
)*(prim
->nbuffers
+1));
847 prim
->buffers
= bufs
;
850 prim
->buffers
[prim
->nbuffers
++] = This
;
852 /* Disable until initialized.. */
853 This
->ds3dmode
= DS3DMODE_DISABLE
;
859 DS8Buffer_Destroy(This
);
863 void DS8Buffer_Destroy(DS8Buffer
*This
)
865 DS8Primary
*prim
= This
->primary
;
868 TRACE("Destroying %p\n", This
);
870 EnterCriticalSection(prim
->crst
);
871 /* Remove from list, if in list */
872 for(idx
= 0;idx
< prim
->nnotifies
;++idx
)
874 if(This
== prim
->notifies
[idx
])
876 prim
->notifies
[idx
] = prim
->notifies
[--prim
->nnotifies
];
880 for(idx
= 0;idx
< prim
->nbuffers
;++idx
)
882 if(prim
->buffers
[idx
] == This
)
884 prim
->buffers
[idx
] = prim
->buffers
[--prim
->nbuffers
];
889 setALContext(This
->ctx
);
892 alSourceStop(This
->source
);
893 alSourcei(This
->source
, AL_BUFFER
, 0);
896 prim
->sources
[prim
->parent
->share
->nsources
++] = This
->source
;
899 LeaveCriticalSection(prim
->crst
);
902 DS8Data_Release(This
->buffer
);
906 HeapFree(GetProcessHeap(), 0, This
->notify
);
907 HeapFree(GetProcessHeap(), 0, This
);
911 static HRESULT WINAPI
DS8Buffer_QueryInterface(IDirectSoundBuffer8
*iface
, REFIID riid
, void **ppv
)
913 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
915 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
918 if(IsEqualIID(riid
, &IID_IUnknown
))
919 *ppv
= &This
->IDirectSoundBuffer8_iface
;
920 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
921 *ppv
= &This
->IDirectSoundBuffer_iface
;
922 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer8
))
924 if(This
->primary
->parent
->is_8
)
925 *ppv
= &This
->IDirectSoundBuffer8_iface
;
927 else if(IsEqualIID(riid
, &IID_IDirectSound3DBuffer
))
929 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
930 *ppv
= &This
->IDirectSound3DBuffer_iface
;
932 else if(IsEqualIID(riid
, &IID_IDirectSoundNotify
))
934 if((This
->buffer
->dsbflags
&DSBCAPS_CTRLPOSITIONNOTIFY
))
935 *ppv
= &This
->IDirectSoundNotify_iface
;
937 else if(IsEqualIID(riid
, &IID_IKsPropertySet
))
938 *ppv
= &This
->IKsPropertySet_iface
;
940 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
944 IUnknown_AddRef((IUnknown
*)*ppv
);
948 return E_NOINTERFACE
;
951 static ULONG WINAPI
DS8Buffer_AddRef(IDirectSoundBuffer8
*iface
)
953 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
956 InterlockedIncrement(&This
->all_ref
);
957 ret
= InterlockedIncrement(&This
->ref
);
958 TRACE("new refcount %"LONGFMT
"d\n", ret
);
963 static ULONG WINAPI
DS8Buffer_Release(IDirectSoundBuffer8
*iface
)
965 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
968 ret
= InterlockedDecrement(&This
->ref
);
969 TRACE("new refcount %"LONGFMT
"d\n", ret
);
970 if(InterlockedDecrement(&This
->all_ref
) == 0)
971 DS8Buffer_Destroy(This
);
976 static HRESULT WINAPI
DS8Buffer_GetCaps(IDirectSoundBuffer8
*iface
, DSBCAPS
*caps
)
978 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
980 TRACE("(%p)->(%p)\n", iface
, caps
);
982 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
984 WARN("Invalid DSBCAPS (%p, %"LONGFMT
"u)\n", caps
, (caps
? caps
->dwSize
: 0));
985 return DSERR_INVALIDPARAM
;
988 caps
->dwFlags
= This
->buffer
->dsbflags
;
989 caps
->dwBufferBytes
= This
->buffer
->buf_size
;
990 caps
->dwUnlockTransferRate
= 4096;
991 caps
->dwPlayCpuOverhead
= 0;
995 static HRESULT WINAPI
DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD
*playpos
, DWORD
*curpos
)
997 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
998 UINT writecursor
, pos
;
1000 TRACE("(%p)->(%p, %p)\n", iface
, playpos
, curpos
);
1002 if(This
->buffer
->numsegs
> 1)
1004 ALint queued
= QBUFFERS
;
1006 EnterCriticalSection(This
->crst
);
1008 setALContext(This
->ctx
);
1009 alGetSourcei(This
->source
, AL_BUFFERS_QUEUED
, &queued
);
1013 pos
= (This
->curidx
+This
->buffer
->numsegs
-queued
)%This
->buffer
->numsegs
;
1014 pos
*= This
->buffer
->segsize
;
1015 writecursor
= This
->curidx
* This
->buffer
->segsize
;
1017 LeaveCriticalSection(This
->crst
);
1019 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SUB_DATA
] ||
1020 This
->primary
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
1022 ALint rwpos
[2] = { 0, 0 };
1024 setALContext(This
->ctx
);
1025 alGetSourceiv(This
->source
, AL_BYTE_RW_OFFSETS_SOFT
, rwpos
);
1030 writecursor
= rwpos
[1];
1034 const WAVEFORMATEX
*format
= &This
->buffer
->format
.Format
;
1038 setALContext(This
->ctx
);
1039 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
1040 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
1045 if(status
== AL_PLAYING
)
1047 writecursor
= format
->nSamplesPerSec
/ 100;
1048 writecursor
*= format
->nBlockAlign
;
1052 writecursor
= (writecursor
+ pos
) % This
->buffer
->buf_size
;
1054 TRACE("%p Play pos = %u, write pos = %u\n", This
, pos
, writecursor
);
1056 if(pos
>= This
->buffer
->buf_size
)
1058 ERR("playpos >= buf_size\n");
1059 pos
%= This
->buffer
->buf_size
;
1061 if(writecursor
>= This
->buffer
->buf_size
)
1063 ERR("writepos >= buf_size\n");
1064 writecursor
%= This
->buffer
->buf_size
;
1067 if(playpos
) *playpos
= pos
;
1068 if(curpos
) *curpos
= writecursor
;
1073 static HRESULT WINAPI
DS8Buffer_GetFormat(IDirectSoundBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
1075 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1079 TRACE("(%p)->(%p, %"LONGFMT
"u, %p)\n", iface
, wfx
, allocated
, written
);
1081 if(!wfx
&& !written
)
1083 WARN("Cannot report format or format size\n");
1084 return DSERR_INVALIDPARAM
;
1087 size
= sizeof(This
->buffer
->format
.Format
) + This
->buffer
->format
.Format
.cbSize
;
1090 if(allocated
< size
)
1091 hr
= DSERR_INVALIDPARAM
;
1093 memcpy(wfx
, &This
->buffer
->format
.Format
, size
);
1101 static HRESULT WINAPI
DS8Buffer_GetVolume(IDirectSoundBuffer8
*iface
, LONG
*vol
)
1103 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1106 TRACE("(%p)->(%p)\n", iface
, vol
);
1110 WARN("Invalid pointer\n");
1111 return DSERR_INVALIDPARAM
;
1114 hr
= DSERR_CONTROLUNAVAIL
;
1115 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1116 WARN("Volume control not set\n");
1119 ALfloat gain
= 1.0f
;
1121 setALContext(This
->ctx
);
1122 alGetSourcef(This
->source
, AL_GAIN
, &gain
);
1126 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
1133 static HRESULT WINAPI
DS8Buffer_GetPan(IDirectSoundBuffer8
*iface
, LONG
*pan
)
1135 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1138 TRACE("(%p)->(%p)\n", iface
, pan
);
1142 WARN("Invalid pointer\n");
1143 return DSERR_INVALIDPARAM
;
1146 hr
= DSERR_CONTROLUNAVAIL
;
1147 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1148 WARN("Panning control not set\n");
1153 setALContext(This
->ctx
);
1154 alGetSourcefv(This
->source
, AL_POSITION
, pos
);
1158 *pan
= clampI(((pos
[0]+1.0) * (DSBPAN_RIGHT
-DSBPAN_LEFT
) / 2.0 + 0.5) + DSBPAN_LEFT
, DSBPAN_LEFT
, DSBPAN_RIGHT
);
1165 static HRESULT WINAPI
DS8Buffer_GetFrequency(IDirectSoundBuffer8
*iface
, DWORD
*freq
)
1167 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1170 TRACE("(%p)->(%p)\n", iface
, freq
);
1174 WARN("Invalid pointer\n");
1175 return DSERR_INVALIDPARAM
;
1178 hr
= DSERR_CONTROLUNAVAIL
;
1179 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1180 WARN("Frequency control not set\n");
1183 ALfloat pitch
= 1.0f
;
1185 setALContext(This
->ctx
);
1186 alGetSourcefv(This
->source
, AL_PITCH
, &pitch
);
1190 *freq
= (DWORD
)(This
->buffer
->format
.Format
.nSamplesPerSec
* pitch
);
1197 static HRESULT WINAPI
DS8Buffer_GetStatus(IDirectSoundBuffer8
*iface
, DWORD
*status
)
1199 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1200 ALint state
, looping
;
1202 TRACE("(%p)->(%p)\n", iface
, status
);
1206 WARN("Invalid pointer\n");
1207 return DSERR_INVALIDPARAM
;
1211 if(This
->buffer
->numsegs
== 1)
1213 setALContext(This
->ctx
);
1214 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1215 alGetSourcei(This
->source
, AL_LOOPING
, &looping
);
1221 EnterCriticalSection(This
->crst
);
1223 setALContext(This
->ctx
);
1224 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1228 if(state
!= AL_PLAYING
)
1229 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1230 looping
= This
->islooping
;
1232 LeaveCriticalSection(This
->crst
);
1235 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1237 if((This
->buffer
->dsbflags
&DSBCAPS_LOCSOFTWARE
))
1238 *status
|= DSBSTATUS_LOCSOFTWARE
;
1239 else if((This
->buffer
->dsbflags
&DSBCAPS_LOCHARDWARE
))
1240 *status
|= DSBSTATUS_LOCHARDWARE
;
1242 if(state
== AL_PLAYING
)
1243 *status
|= DSBSTATUS_PLAYING
| (looping
? DSBSTATUS_LOOPING
: 0);
1245 TRACE("%p status = 0x%08"LONGFMT
"x\n", This
, *status
);
1249 static HRESULT WINAPI
DS8Buffer_Initialize(IDirectSoundBuffer8
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
1251 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1252 DS3DBUFFER
*ds3dbuffer
;
1255 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
1257 EnterCriticalSection(This
->crst
);
1258 setALContext(This
->ctx
);
1260 hr
= DSERR_ALREADYINITIALIZED
;
1266 hr
= DSERR_INVALIDPARAM
;
1269 WARN("Missing DSound buffer description\n");
1272 if(!desc
->lpwfxFormat
)
1274 WARN("Missing buffer format (%p)\n", This
);
1277 if((desc
->dwFlags
&DSBCAPS_CTRL3D
) && desc
->lpwfxFormat
->nChannels
!= 1)
1279 if(This
->primary
->parent
->is_8
)
1281 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
1283 WARN("Can't create multi-channel 3D buffers\n");
1286 ERR("Multi-channel 3D sounds are not spatialized\n");
1289 hr
= DS8Data_Create(&This
->buffer
, desc
, This
->primary
);
1294 DS8Data
*buf
= This
->buffer
;
1296 if(buf
->format
.Format
.wBitsPerSample
== 8)
1297 memset(buf
->data
, 0x80, buf
->buf_size
);
1299 memset(buf
->data
, 0x00, buf
->buf_size
);
1301 if(This
->primary
->SupportedExt
[EXT_STATIC_BUFFER
])
1302 This
->ExtAL
->BufferDataStatic(buf
->buffers
[0], buf
->buf_format
,
1303 buf
->data
, buf
->buf_size
,
1304 buf
->format
.Format
.nSamplesPerSec
);
1305 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
1306 This
->ExtAL
->BufferSamplesSOFT(buf
->buffers
[0],
1307 buf
->format
.Format
.nSamplesPerSec
, buf
->buf_format
,
1308 buf
->buf_size
/buf
->format
.Format
.nBlockAlign
,
1309 buf
->in_chans
, buf
->in_type
, buf
->data
);
1310 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SUB_DATA
])
1311 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1312 buf
->data
, buf
->buf_size
,
1313 buf
->format
.Format
.nSamplesPerSec
);
1319 if(This
->primary
->parent
->share
->nsources
)
1321 This
->source
= This
->primary
->sources
[--(This
->primary
->parent
->share
->nsources
)];
1322 alSourcef(This
->source
, AL_GAIN
, 1.0f
);
1323 alSourcef(This
->source
, AL_PITCH
, 1.0f
);
1329 ds3dbuffer
= &This
->params
;
1330 ds3dbuffer
->dwSize
= sizeof(This
->params
);
1331 ds3dbuffer
->vPosition
.x
= 0.0;
1332 ds3dbuffer
->vPosition
.y
= 0.0;
1333 ds3dbuffer
->vPosition
.z
= 0.0;
1334 ds3dbuffer
->vVelocity
.x
= 0.0;
1335 ds3dbuffer
->vVelocity
.y
= 0.0;
1336 ds3dbuffer
->vVelocity
.z
= 0.0;
1337 ds3dbuffer
->dwInsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1338 ds3dbuffer
->dwOutsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1339 ds3dbuffer
->vConeOrientation
.x
= 0.0;
1340 ds3dbuffer
->vConeOrientation
.y
= 0.0;
1341 ds3dbuffer
->vConeOrientation
.z
= 1.0;
1342 ds3dbuffer
->lConeOutsideVolume
= DS3D_DEFAULTCONEOUTSIDEVOLUME
;
1343 ds3dbuffer
->flMinDistance
= DS3D_DEFAULTMINDISTANCE
;
1344 ds3dbuffer
->flMaxDistance
= DS3D_DEFAULTMAXDISTANCE
;
1345 ds3dbuffer
->dwMode
= DS3DMODE_NORMAL
;
1347 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
1349 if(This
->primary
->auxslot
!= 0)
1351 alSource3i(This
->source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1355 hr
= IDirectSound3DBuffer_SetAllParameters(&This
->IDirectSound3DBuffer_iface
, ds3dbuffer
, DS3D_IMMEDIATE
);
1358 ERR("SetAllParameters failed\n");
1364 ALuint source
= This
->source
;
1366 if(This
->primary
->auxslot
!= 0)
1368 /* Simple hack to make reverb affect non-3D sounds too */
1369 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1370 /*alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);*/
1373 /* Non-3D sources aren't distance attenuated */
1374 This
->ds3dmode
= DS3DMODE_DISABLE
;
1375 alSource3f(source
, AL_POSITION
, 0.0f
, 1.0f
, 0.0f
);
1376 alSource3f(source
, AL_VELOCITY
, 0.0f
, 0.0f
, 0.0f
);
1377 alSource3f(source
, AL_DIRECTION
, 0.0f
, 0.0f
, 0.0f
);
1378 alSourcef(source
, AL_CONE_OUTER_GAIN
, 1.0f
);
1379 alSourcef(source
, AL_REFERENCE_DISTANCE
, 1.0f
);
1380 alSourcef(source
, AL_MAX_DISTANCE
, 1000.0f
);
1381 alSourcef(source
, AL_ROLLOFF_FACTOR
, 0.0f
);
1382 alSourcei(source
, AL_CONE_INNER_ANGLE
, 360);
1383 alSourcei(source
, AL_CONE_OUTER_ANGLE
, 360);
1384 alSourcei(source
, AL_SOURCE_RELATIVE
, AL_TRUE
);
1391 LeaveCriticalSection(This
->crst
);
1396 static HRESULT WINAPI
DS8Buffer_Lock(IDirectSoundBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1398 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1401 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %p, %p, %p, %p, 0x%"LONGFMT
"x)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1405 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
1406 return DSERR_INVALIDPARAM
;
1411 if(ptr2
) *ptr2
= NULL
;
1414 if((flags
&DSBLOCK_FROMWRITECURSOR
))
1415 DS8Buffer_GetCurrentPosition(iface
, NULL
, &ofs
);
1416 else if(ofs
>= This
->buffer
->buf_size
)
1418 WARN("Invalid ofs %"LONGFMT
"u\n", ofs
);
1419 return DSERR_INVALIDPARAM
;
1421 if((flags
&DSBLOCK_ENTIREBUFFER
))
1422 bytes
= This
->buffer
->buf_size
;
1423 else if(bytes
> This
->buffer
->buf_size
)
1425 WARN("Invalid size %"LONGFMT
"u\n", bytes
);
1426 return DSERR_INVALIDPARAM
;
1429 if(InterlockedExchange(&This
->buffer
->locked
, TRUE
) == TRUE
)
1431 WARN("Already locked\n");
1432 return DSERR_INVALIDPARAM
;
1435 *ptr1
= This
->buffer
->data
+ ofs
;
1436 if(ofs
+bytes
>= This
->buffer
->buf_size
)
1438 *len1
= This
->buffer
->buf_size
- ofs
;
1439 remain
= bytes
- *len1
;
1447 if(ptr2
&& len2
&& remain
)
1449 *ptr2
= This
->buffer
->data
;
1456 static HRESULT WINAPI
DS8Buffer_Play(IDirectSoundBuffer8
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1458 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1459 ALint type
, state
= AL_STOPPED
;
1462 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %"LONGFMT
"u)\n", iface
, res1
, prio
, flags
);
1464 EnterCriticalSection(This
->crst
);
1465 setALContext(This
->ctx
);
1467 hr
= DSERR_BUFFERLOST
;
1468 if(This
->bufferlost
)
1470 WARN("Buffer %p lost\n", This
);
1474 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1476 if(!(This
->buffer
->dsbflags
&(DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCSOFTWARE
)))
1478 if(flags
& DSBPLAY_LOCSOFTWARE
)
1479 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1481 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1486 ERR("Invalid priority set for non-deferred buffer %p, %"LONGFMT
"u!\n", This
->buffer
, prio
);
1487 hr
= DSERR_INVALIDPARAM
;
1491 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1492 if(This
->buffer
->numsegs
> 1)
1494 This
->islooping
= !!(flags
&DSBPLAY_LOOPING
);
1495 if(state
!= AL_PLAYING
&& This
->isplaying
)
1500 alGetSourcei(This
->source
, AL_SOURCE_TYPE
, &type
);
1501 alSourcei(This
->source
, AL_LOOPING
, (flags
&DSBPLAY_LOOPING
) ? AL_TRUE
: AL_FALSE
);
1506 if(state
== AL_PLAYING
)
1509 /* alSourceQueueBuffers will implicitly set type to streaming */
1510 if(This
->buffer
->numsegs
== 1)
1512 if(type
!= AL_STATIC
)
1513 alSourcei(This
->source
, AL_BUFFER
, This
->buffer
->buffers
[0]);
1514 alSourcePlay(This
->source
);
1516 if(alGetError() != AL_NO_ERROR
)
1518 ERR("Couldn't start source\n");
1519 This
->curidx
= (This
->buffer
->numsegs
-1+This
->curidx
)%This
->buffer
->numsegs
;
1520 alSourcei(This
->source
, AL_BUFFER
, 0);
1525 This
->isplaying
= TRUE
;
1529 DS8Buffer_addnotify(This
);
1530 DS8Primary_starttimer(This
->primary
);
1532 else if(This
->buffer
->numsegs
> 1)
1533 DS8Primary_starttimer(This
->primary
);
1537 LeaveCriticalSection(This
->crst
);
1541 static HRESULT WINAPI
DS8Buffer_SetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD pos
)
1543 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1545 TRACE("(%p)->(%"LONGFMT
"u)\n", iface
, pos
);
1547 if(pos
>= This
->buffer
->buf_size
)
1548 return DSERR_INVALIDPARAM
;
1550 EnterCriticalSection(This
->crst
);
1552 if(This
->buffer
->numsegs
> 1)
1554 DS8Data
*buf
= This
->buffer
;
1555 This
->curidx
= pos
/buf
->segsize
;
1556 if(This
->curidx
>= buf
->numsegs
)
1557 This
->curidx
= buf
->numsegs
- 1;
1560 setALContext(This
->ctx
);
1561 /* Perform a flush, so the next timer update will restart at the
1562 * proper position */
1563 alSourceStop(This
->source
);
1564 alSourcei(This
->source
, AL_BUFFER
, 0);
1571 setALContext(This
->ctx
);
1572 alSourcei(This
->source
, AL_BYTE_OFFSET
, pos
);
1575 This
->lastpos
= pos
;
1577 LeaveCriticalSection(This
->crst
);
1581 static HRESULT WINAPI
DS8Buffer_SetFormat(IDirectSoundBuffer8
*iface
, const WAVEFORMATEX
*wfx
)
1583 /* This call only works on primary buffers */
1584 WARN("(%p)->(%p)\n", iface
, wfx
);
1585 return DSERR_INVALIDCALL
;
1588 static HRESULT WINAPI
DS8Buffer_SetVolume(IDirectSoundBuffer8
*iface
, LONG vol
)
1590 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1593 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, vol
);
1595 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
1597 WARN("Invalid volume (%"LONGFMT
"d)\n", vol
);
1598 return DSERR_INVALIDPARAM
;
1601 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1602 hr
= DSERR_CONTROLUNAVAIL
;
1605 ALfloat fvol
= mB_to_gain(vol
);
1606 setALContext(This
->ctx
);
1607 alSourcef(This
->source
, AL_GAIN
, fvol
);
1614 static HRESULT WINAPI
DS8Buffer_SetPan(IDirectSoundBuffer8
*iface
, LONG pan
)
1616 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1619 TRACE("(%p)->(%"LONGFMT
"d)\n", iface
, pan
);
1621 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
1623 WARN("invalid parameter: pan = %"LONGFMT
"d\n", pan
);
1624 return DSERR_INVALIDPARAM
;
1627 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1628 hr
= DSERR_CONTROLUNAVAIL
;
1632 pos
[0] = (pan
-DSBPAN_LEFT
) * 2.0 / (ALfloat
)(DSBPAN_RIGHT
-DSBPAN_LEFT
) - 1.0;
1633 /* NOTE: Strict movement along the X plane can cause the sound to jump
1634 * between left and right sharply. Using a curved path helps smooth it
1636 pos
[1] = sqrt(1.0 - pos
[0]*pos
[0]);
1639 setALContext(This
->ctx
);
1640 alSourcefv(This
->source
, AL_POSITION
, pos
);
1644 if(pan
!= 0 && This
->buffer
->format
.Format
.nChannels
> 1)
1645 FIXME("Panning for multi-channel buffers is not supported\n");
1651 static HRESULT WINAPI
DS8Buffer_SetFrequency(IDirectSoundBuffer8
*iface
, DWORD freq
)
1653 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1656 TRACE("(%p)->(%"LONGFMT
"u)\n", iface
, freq
);
1658 if(freq
< DSBFREQUENCY_MIN
|| freq
> DSBFREQUENCY_MAX
)
1660 WARN("invalid parameter: freq = %"LONGFMT
"u\n", freq
);
1661 return DSERR_INVALIDPARAM
;
1664 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1665 hr
= DSERR_CONTROLUNAVAIL
;
1668 ALfloat pitch
= 1.0f
;
1669 if(freq
!= DSBFREQUENCY_ORIGINAL
)
1670 pitch
= freq
/ (ALfloat
)This
->buffer
->format
.Format
.nSamplesPerSec
;
1672 setALContext(This
->ctx
);
1673 alSourcef(This
->source
, AL_PITCH
, pitch
);
1681 static HRESULT WINAPI
DS8Buffer_Stop(IDirectSoundBuffer8
*iface
)
1683 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1686 TRACE("(%p)->()\n", iface
);
1688 EnterCriticalSection(This
->crst
);
1689 setALContext(This
->ctx
);
1691 alSourcePause(This
->source
);
1693 /* Mac OS X doesn't immediately report state change
1694 * if Play() is immediately called after Stop, this can be fatal,
1695 * the buffer would never be restarted
1699 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1700 if(state
!= AL_PLAYING
)
1705 This
->isplaying
= FALSE
;
1708 LeaveCriticalSection(This
->crst
);
1713 static HRESULT WINAPI
DS8Buffer_Unlock(IDirectSoundBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1715 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1716 DS8Data
*buf
= This
->buffer
;
1717 DWORD bufsize
= buf
->buf_size
;
1718 DWORD_PTR ofs1
, ofs2
;
1719 DWORD_PTR boundary
= (DWORD_PTR
)buf
->data
;
1722 TRACE("(%p)->(%p, %"LONGFMT
"u, %p, %"LONGFMT
"u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1724 if(InterlockedExchange(&This
->buffer
->locked
, FALSE
) == FALSE
)
1726 WARN("Not locked\n");
1727 return DSERR_INVALIDPARAM
;
1730 hr
= DSERR_INVALIDPARAM
;
1731 /* Make sure offset is between boundary and boundary + bufsize */
1732 ofs1
= (DWORD_PTR
)ptr1
;
1733 ofs2
= (DWORD_PTR
)ptr2
;
1736 if(ofs2
&& ofs2
!= boundary
)
1740 if(bufsize
-ofs1
< len1
|| len2
> ofs1
)
1748 if(This
->primary
->SupportedExt
[EXT_STATIC_BUFFER
])
1751 setALContext(This
->ctx
);
1752 if(This
->primary
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
1754 const WAVEFORMATEX
*format
= &buf
->format
.Format
;
1756 ptr1
= (BYTE
*)ptr1
- (ofs1
%format
->nBlockAlign
);
1757 ofs1
/= format
->nBlockAlign
;
1758 len1
/= format
->nBlockAlign
;
1760 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs1
, len1
,
1761 buf
->in_chans
, buf
->in_type
, ptr1
);
1762 ptr2
= (BYTE
*)ptr2
- (ofs2
%format
->nBlockAlign
);
1763 ofs2
/= format
->nBlockAlign
;
1764 len2
/= format
->nBlockAlign
;
1766 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs2
, len2
,
1767 buf
->in_chans
, buf
->in_type
, ptr2
);
1770 else if(This
->primary
->SupportedExt
[SOFT_BUFFER_SUB_DATA
])
1772 const WAVEFORMATEX
*format
= &buf
->format
.Format
;
1774 len1
-= len1
%format
->nBlockAlign
;
1776 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr1
,
1778 len2
-= len2
%format
->nBlockAlign
;
1780 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr2
,
1786 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1787 buf
->data
, buf
->buf_size
,
1788 buf
->format
.Format
.nSamplesPerSec
);
1795 WARN("Invalid parameters (0x%lx,%"LONGFMT
"u) (%p,%"LONGFMT
"u,%p,%"LONGFMT
"u)\n", boundary
, bufsize
, ptr1
, len1
, ptr2
, len2
);
1799 static HRESULT WINAPI
DS8Buffer_Restore(IDirectSoundBuffer8
*iface
)
1801 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1804 TRACE("(%p)->()\n", iface
);
1806 EnterCriticalSection(This
->crst
);
1807 if(This
->primary
->parent
->prio_level
< DSSCL_WRITEPRIMARY
||
1808 iface
== This
->primary
->write_emu
)
1810 This
->bufferlost
= 0;
1814 hr
= DSERR_BUFFERLOST
;
1815 LeaveCriticalSection(This
->crst
);
1820 static HRESULT WINAPI
DS8Buffer_SetFX(IDirectSoundBuffer8
*iface
, DWORD fxcount
, DSEFFECTDESC
*desc
, DWORD
*rescodes
)
1822 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1825 TRACE("(%p)->(%"LONGFMT
"u, %p, %p)\n", This
, fxcount
, desc
, rescodes
);
1827 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFX
))
1829 WARN("FX control not set\n");
1830 return DSERR_CONTROLUNAVAIL
;
1835 if(desc
|| rescodes
)
1837 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1838 return DSERR_INVALIDPARAM
;
1841 /* No effects; we can handle that */
1845 if(!desc
|| !rescodes
)
1847 WARN("NULL desc and/or result pointer specified.\n");
1848 return DSERR_INVALIDPARAM
;
1851 /* We don't (currently) handle DSound effects */
1852 for(i
= 0;i
< fxcount
;++i
)
1854 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc
[i
].guidDSFXClass
));
1855 rescodes
[i
] = DSFXR_FAILED
;
1858 return DS_INCOMPLETE
;
1861 static HRESULT WINAPI
DS8Buffer_AcquireResources(IDirectSoundBuffer8
*iface
, DWORD flags
, DWORD fxcount
, DWORD
*rescodes
)
1863 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1865 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %p)\n", This
, flags
, fxcount
, rescodes
);
1867 /* effects aren't supported at the moment.. */
1868 if(fxcount
!= 0 || rescodes
)
1870 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1871 return DSERR_INVALIDPARAM
;
1874 EnterCriticalSection(This
->crst
);
1875 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1877 This
->buffer
->dsbflags
&= ~(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
);
1878 if((flags
&DSBPLAY_LOCSOFTWARE
))
1879 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1881 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1883 LeaveCriticalSection(This
->crst
);
1888 static HRESULT WINAPI
DS8Buffer_GetObjectInPath(IDirectSoundBuffer8
*iface
, REFGUID guid
, DWORD idx
, REFGUID rguidiface
, void **ppv
)
1890 FIXME("(%p)->(%s, %"LONGFMT
"u, %s, %p) : stub!\n", iface
, debugstr_guid(guid
), idx
, debugstr_guid(rguidiface
), ppv
);
1894 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
= {
1895 DS8Buffer_QueryInterface
,
1899 DS8Buffer_GetCurrentPosition
,
1900 DS8Buffer_GetFormat
,
1901 DS8Buffer_GetVolume
,
1903 DS8Buffer_GetFrequency
,
1904 DS8Buffer_GetStatus
,
1905 DS8Buffer_Initialize
,
1908 DS8Buffer_SetCurrentPosition
,
1909 DS8Buffer_SetFormat
,
1910 DS8Buffer_SetVolume
,
1912 DS8Buffer_SetFrequency
,
1917 DS8Buffer_AcquireResources
,
1918 DS8Buffer_GetObjectInPath
1922 static HRESULT WINAPI
DSBuffer_QueryInterface(IDirectSoundBuffer
*iface
, REFIID riid
, void **ppv
)
1924 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1925 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
1928 static ULONG WINAPI
DSBuffer_AddRef(IDirectSoundBuffer
*iface
)
1930 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1931 return DS8Buffer_AddRef(&This
->IDirectSoundBuffer8_iface
);
1934 static ULONG WINAPI
DSBuffer_Release(IDirectSoundBuffer
*iface
)
1936 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1937 return DS8Buffer_Release(&This
->IDirectSoundBuffer8_iface
);
1940 static HRESULT WINAPI
DSBuffer_GetCaps(IDirectSoundBuffer
*iface
, DSBCAPS
*caps
)
1942 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1943 return DS8Buffer_GetCaps(&This
->IDirectSoundBuffer8_iface
, caps
);
1946 static HRESULT WINAPI
DSBuffer_GetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD
*playpos
, DWORD
*curpos
)
1948 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1949 return DS8Buffer_GetCurrentPosition(&This
->IDirectSoundBuffer8_iface
, playpos
, curpos
);
1952 static HRESULT WINAPI
DSBuffer_GetFormat(IDirectSoundBuffer
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
1954 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1955 return DS8Buffer_GetFormat(&This
->IDirectSoundBuffer8_iface
, wfx
, allocated
, written
);
1958 static HRESULT WINAPI
DSBuffer_GetVolume(IDirectSoundBuffer
*iface
, LONG
*vol
)
1960 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1961 return DS8Buffer_GetVolume(&This
->IDirectSoundBuffer8_iface
, vol
);
1964 static HRESULT WINAPI
DSBuffer_GetPan(IDirectSoundBuffer
*iface
, LONG
*pan
)
1966 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1967 return DS8Buffer_GetPan(&This
->IDirectSoundBuffer8_iface
, pan
);
1970 static HRESULT WINAPI
DSBuffer_GetFrequency(IDirectSoundBuffer
*iface
, DWORD
*freq
)
1972 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1973 return DS8Buffer_GetFrequency(&This
->IDirectSoundBuffer8_iface
, freq
);
1976 static HRESULT WINAPI
DSBuffer_GetStatus(IDirectSoundBuffer
*iface
, DWORD
*status
)
1978 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1979 return DS8Buffer_GetStatus(&This
->IDirectSoundBuffer8_iface
, status
);
1982 static HRESULT WINAPI
DSBuffer_Initialize(IDirectSoundBuffer
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
1984 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1985 return DS8Buffer_Initialize(&This
->IDirectSoundBuffer8_iface
, ds
, desc
);
1988 static HRESULT WINAPI
DSBuffer_Lock(IDirectSoundBuffer
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1990 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1991 return DS8Buffer_Lock(&This
->IDirectSoundBuffer8_iface
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1994 static HRESULT WINAPI
DSBuffer_Play(IDirectSoundBuffer
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1996 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
1997 return DS8Buffer_Play(&This
->IDirectSoundBuffer8_iface
, res1
, prio
, flags
);
2000 static HRESULT WINAPI
DSBuffer_SetCurrentPosition(IDirectSoundBuffer
*iface
, DWORD pos
)
2002 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2003 return DS8Buffer_SetCurrentPosition(&This
->IDirectSoundBuffer8_iface
, pos
);
2006 static HRESULT WINAPI
DSBuffer_SetFormat(IDirectSoundBuffer
*iface
, const WAVEFORMATEX
*wfx
)
2008 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2009 return DS8Buffer_SetFormat(&This
->IDirectSoundBuffer8_iface
, wfx
);
2012 static HRESULT WINAPI
DSBuffer_SetVolume(IDirectSoundBuffer
*iface
, LONG vol
)
2014 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2015 return DS8Buffer_SetVolume(&This
->IDirectSoundBuffer8_iface
, vol
);
2018 static HRESULT WINAPI
DSBuffer_SetPan(IDirectSoundBuffer
*iface
, LONG pan
)
2020 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2021 return DS8Buffer_SetPan(&This
->IDirectSoundBuffer8_iface
, pan
);
2024 static HRESULT WINAPI
DSBuffer_SetFrequency(IDirectSoundBuffer
*iface
, DWORD freq
)
2026 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2027 return DS8Buffer_SetFrequency(&This
->IDirectSoundBuffer8_iface
, freq
);
2030 static HRESULT WINAPI
DSBuffer_Stop(IDirectSoundBuffer
*iface
)
2032 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2033 return DS8Buffer_Stop(&This
->IDirectSoundBuffer8_iface
);
2036 static HRESULT WINAPI
DSBuffer_Unlock(IDirectSoundBuffer
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
2038 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2039 return DS8Buffer_Unlock(&This
->IDirectSoundBuffer8_iface
, ptr1
, len1
, ptr2
, len2
);
2042 static HRESULT WINAPI
DSBuffer_Restore(IDirectSoundBuffer
*iface
)
2044 DS8Buffer
*This
= impl_from_IDirectSoundBuffer(iface
);
2045 return DS8Buffer_Restore(&This
->IDirectSoundBuffer8_iface
);
2048 static const IDirectSoundBufferVtbl DSBuffer_Vtbl
= {
2049 DSBuffer_QueryInterface
,
2053 DSBuffer_GetCurrentPosition
,
2057 DSBuffer_GetFrequency
,
2059 DSBuffer_Initialize
,
2062 DSBuffer_SetCurrentPosition
,
2066 DSBuffer_SetFrequency
,
2073 void DS8Buffer_SetParams(DS8Buffer
*This
, const DS3DBUFFER
*params
, LONG flags
)
2075 const ALuint source
= This
->source
;
2076 union BufferParamFlags dirty
= { flags
};
2079 alSource3f(source
, AL_POSITION
, params
->vPosition
.x
, params
->vPosition
.y
,
2080 -params
->vPosition
.z
);
2082 alSource3f(source
, AL_VELOCITY
, params
->vVelocity
.x
, params
->vVelocity
.y
,
2083 -params
->vVelocity
.z
);
2084 if(dirty
.bit
.cone_angles
)
2086 alSourcei(source
, AL_CONE_INNER_ANGLE
, params
->dwInsideConeAngle
);
2087 alSourcei(source
, AL_CONE_OUTER_ANGLE
, params
->dwOutsideConeAngle
);
2089 if(dirty
.bit
.cone_orient
)
2090 alSource3f(source
, AL_DIRECTION
, params
->vConeOrientation
.x
,
2091 params
->vConeOrientation
.y
,
2092 -params
->vConeOrientation
.z
);
2093 if(dirty
.bit
.cone_outsidevolume
)
2094 alSourcef(source
, AL_CONE_OUTER_GAIN
, mB_to_gain(params
->lConeOutsideVolume
));
2095 if(dirty
.bit
.min_distance
)
2096 alSourcef(source
, AL_REFERENCE_DISTANCE
, params
->flMinDistance
);
2097 if(dirty
.bit
.max_distance
)
2098 alSourcef(source
, AL_MAX_DISTANCE
, params
->flMaxDistance
);
2101 This
->ds3dmode
= params
->dwMode
;
2102 alSourcei(source
, AL_SOURCE_RELATIVE
, (params
->dwMode
!=DS3DMODE_NORMAL
) ?
2103 AL_TRUE
: AL_FALSE
);
2104 alSourcef(source
, AL_ROLLOFF_FACTOR
, (params
->dwMode
==DS3DMODE_DISABLE
) ?
2105 0.0f
: This
->primary
->rollofffactor
);
2109 static HRESULT WINAPI
DS8Buffer3D_QueryInterface(IDirectSound3DBuffer
*iface
, REFIID riid
, void **ppv
)
2111 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2112 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2115 static ULONG WINAPI
DS8Buffer3D_AddRef(IDirectSound3DBuffer
*iface
)
2117 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2120 InterlockedIncrement(&This
->all_ref
);
2121 ret
= InterlockedIncrement(&This
->ds3d_ref
);
2122 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2127 static ULONG WINAPI
DS8Buffer3D_Release(IDirectSound3DBuffer
*iface
)
2129 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2132 ret
= InterlockedDecrement(&This
->ds3d_ref
);
2133 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2134 if(InterlockedDecrement(&This
->all_ref
) == 0)
2135 DS8Buffer_Destroy(This
);
2140 static HRESULT WINAPI
DS8Buffer3D_GetAllParameters(IDirectSound3DBuffer
*iface
, DS3DBUFFER
*ds3dbuffer
)
2142 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2144 TRACE("(%p)->(%p)\n", iface
, ds3dbuffer
);
2146 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2148 WARN("Invalid parameters %p %"LONGFMT
"u\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2149 return DSERR_INVALIDPARAM
;
2152 EnterCriticalSection(This
->crst
);
2153 setALContext(This
->ctx
);
2155 IDirectSound3DBuffer_GetPosition(iface
, &ds3dbuffer
->vPosition
);
2156 IDirectSound3DBuffer_GetVelocity(iface
, &ds3dbuffer
->vVelocity
);
2157 IDirectSound3DBuffer_GetConeAngles(iface
, &ds3dbuffer
->dwInsideConeAngle
, &ds3dbuffer
->dwOutsideConeAngle
);
2158 IDirectSound3DBuffer_GetConeOrientation(iface
, &ds3dbuffer
->vConeOrientation
);
2159 IDirectSound3DBuffer_GetConeOutsideVolume(iface
, &ds3dbuffer
->lConeOutsideVolume
);
2160 IDirectSound3DBuffer_GetMinDistance(iface
, &ds3dbuffer
->flMinDistance
);
2161 IDirectSound3DBuffer_GetMaxDistance(iface
, &ds3dbuffer
->flMaxDistance
);
2162 IDirectSound3DBuffer_GetMode(iface
, &ds3dbuffer
->dwMode
);
2165 LeaveCriticalSection(This
->crst
);
2170 static HRESULT WINAPI
DS8Buffer3D_GetConeAngles(IDirectSound3DBuffer
*iface
, DWORD
*pdwInsideConeAngle
, DWORD
*pdwOutsideConeAngle
)
2172 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2173 ALint inangle
, outangle
;
2175 TRACE("(%p)->(%p, %p)\n", This
, pdwInsideConeAngle
, pdwOutsideConeAngle
);
2176 if(!pdwInsideConeAngle
|| !pdwOutsideConeAngle
)
2178 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle
, pdwOutsideConeAngle
);
2179 return DSERR_INVALIDPARAM
;
2182 EnterCriticalSection(This
->crst
);
2183 setALContext(This
->ctx
);
2185 alGetSourcei(This
->source
, AL_CONE_INNER_ANGLE
, &inangle
);
2186 alGetSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, &outangle
);
2190 LeaveCriticalSection(This
->crst
);
2192 *pdwInsideConeAngle
= inangle
;
2193 *pdwOutsideConeAngle
= outangle
;
2197 static HRESULT WINAPI
DS8Buffer3D_GetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVECTOR
*orient
)
2199 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2202 TRACE("(%p)->(%p)\n", This
, orient
);
2205 WARN("Invalid pointer\n");
2206 return DSERR_INVALIDPARAM
;
2209 setALContext(This
->ctx
);
2210 alGetSourcefv(This
->source
, AL_DIRECTION
, dir
);
2216 orient
->z
= -dir
[2];
2220 static HRESULT WINAPI
DS8Buffer3D_GetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG
*vol
)
2222 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2225 TRACE("(%p)->(%p)\n", This
, vol
);
2228 WARN("Invalid pointer\n");
2229 return DSERR_INVALIDPARAM
;
2232 setALContext(This
->ctx
);
2233 alGetSourcef(This
->source
, AL_CONE_OUTER_GAIN
, &gain
);
2237 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
2241 static HRESULT WINAPI
DS8Buffer3D_GetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*maxdist
)
2243 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2246 TRACE("(%p)->(%p)\n", This
, maxdist
);
2249 WARN("Invalid pointer\n");
2250 return DSERR_INVALIDPARAM
;
2253 setALContext(This
->ctx
);
2254 alGetSourcef(This
->source
, AL_MAX_DISTANCE
, &dist
);
2262 static HRESULT WINAPI
DS8Buffer3D_GetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*mindist
)
2264 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2267 TRACE("(%p)->(%p)\n", This
, mindist
);
2270 WARN("Invalid pointer\n");
2271 return DSERR_INVALIDPARAM
;
2274 setALContext(This
->ctx
);
2275 alGetSourcef(This
->source
, AL_REFERENCE_DISTANCE
, &dist
);
2283 static HRESULT WINAPI
DS8Buffer3D_GetMode(IDirectSound3DBuffer
*iface
, DWORD
*mode
)
2285 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2287 TRACE("(%p)->(%p)\n", This
, mode
);
2290 WARN("Invalid pointer\n");
2291 return DSERR_INVALIDPARAM
;
2294 EnterCriticalSection(This
->crst
);
2295 *mode
= This
->ds3dmode
;
2296 LeaveCriticalSection(This
->crst
);
2301 static HRESULT WINAPI
DS8Buffer3D_GetPosition(IDirectSound3DBuffer
*iface
, D3DVECTOR
*pos
)
2303 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2306 TRACE("(%p)->(%p)\n", This
, pos
);
2309 WARN("Invalid pointer\n");
2310 return DSERR_INVALIDPARAM
;
2313 setALContext(This
->ctx
);
2314 alGetSourcefv(This
->source
, AL_POSITION
, alpos
);
2324 static HRESULT WINAPI
DS8Buffer3D_GetVelocity(IDirectSound3DBuffer
*iface
, D3DVECTOR
*vel
)
2326 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2329 TRACE("(%p)->(%p)\n", This
, vel
);
2332 WARN("Invalid pointer\n");
2333 return DSERR_INVALIDPARAM
;
2336 setALContext(This
->ctx
);
2337 alGetSourcefv(This
->source
, AL_VELOCITY
, alvel
);
2347 static HRESULT WINAPI
DS8Buffer3D_SetAllParameters(IDirectSound3DBuffer
*iface
, const DS3DBUFFER
*ds3dbuffer
, DWORD apply
)
2349 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2350 TRACE("(%p)->(%p, %"LONGFMT
"u)\n", This
, ds3dbuffer
, apply
);
2352 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2354 WARN("Invalid DS3DBUFFER (%p, %"LONGFMT
"u)\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2355 return DSERR_INVALIDPARAM
;
2358 if(ds3dbuffer
->dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2359 ds3dbuffer
->dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2361 WARN("Invalid cone angles (%"LONGFMT
"u, %"LONGFMT
"u)\n",
2362 ds3dbuffer
->dwInsideConeAngle
, ds3dbuffer
->dwOutsideConeAngle
);
2363 return DSERR_INVALIDPARAM
;
2366 if(ds3dbuffer
->lConeOutsideVolume
> DSBVOLUME_MAX
||
2367 ds3dbuffer
->lConeOutsideVolume
< DSBVOLUME_MIN
)
2369 WARN("Invalid cone outside volume (%"LONGFMT
"d)\n", ds3dbuffer
->lConeOutsideVolume
);
2370 return DSERR_INVALIDPARAM
;
2373 if(ds3dbuffer
->flMaxDistance
< 0.0f
)
2375 WARN("Invalid max distance (%f)\n", ds3dbuffer
->flMaxDistance
);
2376 return DSERR_INVALIDPARAM
;
2379 if(ds3dbuffer
->flMinDistance
< 0.0f
)
2381 WARN("Invalid min distance (%f)\n", ds3dbuffer
->flMinDistance
);
2382 return DSERR_INVALIDPARAM
;
2385 if(ds3dbuffer
->dwMode
!= DS3DMODE_NORMAL
&&
2386 ds3dbuffer
->dwMode
!= DS3DMODE_HEADRELATIVE
&&
2387 ds3dbuffer
->dwMode
!= DS3DMODE_DISABLE
)
2389 WARN("Invalid mode (%"LONGFMT
"u)\n", ds3dbuffer
->dwMode
);
2390 return DSERR_INVALIDPARAM
;
2393 if(apply
== DS3D_DEFERRED
)
2395 EnterCriticalSection(This
->crst
);
2396 This
->params
= *ds3dbuffer
;
2397 This
->params
.dwSize
= sizeof(This
->params
);
2398 This
->dirty
.bit
.pos
= 1;
2399 This
->dirty
.bit
.vel
= 1;
2400 This
->dirty
.bit
.cone_angles
= 1;
2401 This
->dirty
.bit
.cone_orient
= 1;
2402 This
->dirty
.bit
.cone_outsidevolume
= 1;
2403 This
->dirty
.bit
.min_distance
= 1;
2404 This
->dirty
.bit
.max_distance
= 1;
2405 This
->dirty
.bit
.mode
= 1;
2406 LeaveCriticalSection(This
->crst
);
2410 union BufferParamFlags dirty
= { 0 };
2413 dirty
.bit
.cone_angles
= 1;
2414 dirty
.bit
.cone_orient
= 1;
2415 dirty
.bit
.cone_outsidevolume
= 1;
2416 dirty
.bit
.min_distance
= 1;
2417 dirty
.bit
.max_distance
= 1;
2420 EnterCriticalSection(This
->crst
);
2421 setALContext(This
->ctx
);
2422 DS8Buffer_SetParams(This
, ds3dbuffer
, dirty
.flags
);
2425 LeaveCriticalSection(This
->crst
);
2431 static HRESULT WINAPI
DS8Buffer3D_SetConeAngles(IDirectSound3DBuffer
*iface
, DWORD dwInsideConeAngle
, DWORD dwOutsideConeAngle
, DWORD apply
)
2433 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2435 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u, %"LONGFMT
"u)\n", This
, dwInsideConeAngle
, dwOutsideConeAngle
, apply
);
2436 if(dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2437 dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2439 WARN("Invalid cone angles (%"LONGFMT
"u, %"LONGFMT
"u)\n", dwInsideConeAngle
, dwOutsideConeAngle
);
2440 return DSERR_INVALIDPARAM
;
2443 EnterCriticalSection(This
->crst
);
2444 if(apply
== DS3D_DEFERRED
)
2446 This
->params
.dwInsideConeAngle
= dwInsideConeAngle
;
2447 This
->params
.dwOutsideConeAngle
= dwOutsideConeAngle
;
2448 This
->dirty
.bit
.cone_angles
= 1;
2452 setALContext(This
->ctx
);
2453 alSourcei(This
->source
, AL_CONE_INNER_ANGLE
, dwInsideConeAngle
);
2454 alSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, dwOutsideConeAngle
);
2458 LeaveCriticalSection(This
->crst
);
2463 static HRESULT WINAPI
DS8Buffer3D_SetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2465 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2467 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", This
, x
, y
, z
, apply
);
2469 if(apply
== DS3D_DEFERRED
)
2471 EnterCriticalSection(This
->crst
);
2472 This
->params
.vConeOrientation
.x
= x
;
2473 This
->params
.vConeOrientation
.y
= y
;
2474 This
->params
.vConeOrientation
.z
= z
;
2475 This
->dirty
.bit
.cone_orient
= 1;
2476 LeaveCriticalSection(This
->crst
);
2480 setALContext(This
->ctx
);
2481 alSource3f(This
->source
, AL_DIRECTION
, x
, y
, -z
);
2489 static HRESULT WINAPI
DS8Buffer3D_SetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG vol
, DWORD apply
)
2491 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2493 TRACE("(%p)->(%"LONGFMT
"d, %"LONGFMT
"u)\n", This
, vol
, apply
);
2494 if(vol
< DSBVOLUME_MIN
|| vol
> DSBVOLUME_MAX
)
2496 WARN("Invalid volume (%"LONGFMT
"d)\n", vol
);
2497 return DSERR_INVALIDPARAM
;
2500 if(apply
== DS3D_DEFERRED
)
2502 EnterCriticalSection(This
->crst
);
2503 This
->params
.lConeOutsideVolume
= vol
;
2504 This
->dirty
.bit
.cone_outsidevolume
= 1;
2505 LeaveCriticalSection(This
->crst
);
2509 setALContext(This
->ctx
);
2510 alSourcef(This
->source
, AL_CONE_OUTER_GAIN
, mB_to_gain(vol
));
2518 static HRESULT WINAPI
DS8Buffer3D_SetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE maxdist
, DWORD apply
)
2520 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2522 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", This
, maxdist
, apply
);
2525 WARN("Invalid max distance (%f)\n", maxdist
);
2526 return DSERR_INVALIDPARAM
;
2529 if(apply
== DS3D_DEFERRED
)
2531 EnterCriticalSection(This
->crst
);
2532 This
->params
.flMaxDistance
= maxdist
;
2533 This
->dirty
.bit
.max_distance
= 1;
2534 LeaveCriticalSection(This
->crst
);
2538 setALContext(This
->ctx
);
2539 alSourcef(This
->source
, AL_MAX_DISTANCE
, maxdist
);
2547 static HRESULT WINAPI
DS8Buffer3D_SetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE mindist
, DWORD apply
)
2549 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2551 TRACE("(%p)->(%f, %"LONGFMT
"u)\n", This
, mindist
, apply
);
2554 WARN("Invalid min distance (%f)\n", mindist
);
2555 return DSERR_INVALIDPARAM
;
2558 if(apply
== DS3D_DEFERRED
)
2560 EnterCriticalSection(This
->crst
);
2561 This
->params
.flMinDistance
= mindist
;
2562 This
->dirty
.bit
.min_distance
= 1;
2563 LeaveCriticalSection(This
->crst
);
2567 setALContext(This
->ctx
);
2568 alSourcef(This
->source
, AL_REFERENCE_DISTANCE
, mindist
);
2576 static HRESULT WINAPI
DS8Buffer3D_SetMode(IDirectSound3DBuffer
*iface
, DWORD mode
, DWORD apply
)
2578 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2580 TRACE("(%p)->(%"LONGFMT
"u, %"LONGFMT
"u)\n", This
, mode
, apply
);
2581 if(mode
!= DS3DMODE_NORMAL
&& mode
!= DS3DMODE_HEADRELATIVE
&&
2582 mode
!= DS3DMODE_DISABLE
)
2584 WARN("Invalid mode (%"LONGFMT
"u)\n", mode
);
2585 return DSERR_INVALIDPARAM
;
2588 EnterCriticalSection(This
->crst
);
2589 if(apply
== DS3D_DEFERRED
)
2591 This
->params
.dwMode
= mode
;
2592 This
->dirty
.bit
.mode
= 1;
2596 setALContext(This
->ctx
);
2597 alSourcei(This
->source
, AL_SOURCE_RELATIVE
,
2598 (mode
!= DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
2599 alSourcef(This
->source
, AL_ROLLOFF_FACTOR
,
2600 (mode
== DS3DMODE_DISABLE
) ? 0.0f
: This
->primary
->rollofffactor
);
2601 This
->ds3dmode
= mode
;
2605 LeaveCriticalSection(This
->crst
);
2610 static HRESULT WINAPI
DS8Buffer3D_SetPosition(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2612 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2614 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", This
, x
, y
, z
, apply
);
2616 if(apply
== DS3D_DEFERRED
)
2618 EnterCriticalSection(This
->crst
);
2619 This
->params
.vPosition
.x
= x
;
2620 This
->params
.vPosition
.y
= y
;
2621 This
->params
.vPosition
.z
= z
;
2622 This
->dirty
.bit
.pos
= 1;
2623 LeaveCriticalSection(This
->crst
);
2627 setALContext(This
->ctx
);
2628 alSource3f(This
->source
, AL_POSITION
, x
, y
, -z
);
2636 static HRESULT WINAPI
DS8Buffer3D_SetVelocity(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2638 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2640 TRACE("(%p)->(%f, %f, %f, %"LONGFMT
"u)\n", This
, x
, y
, z
, apply
);
2642 if(apply
== DS3D_DEFERRED
)
2644 EnterCriticalSection(This
->crst
);
2645 This
->params
.vVelocity
.x
= x
;
2646 This
->params
.vVelocity
.y
= y
;
2647 This
->params
.vVelocity
.z
= z
;
2648 This
->dirty
.bit
.vel
= 1;
2649 LeaveCriticalSection(This
->crst
);
2653 setALContext(This
->ctx
);
2654 alSource3f(This
->source
, AL_VELOCITY
, x
, y
, -z
);
2662 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
=
2664 DS8Buffer3D_QueryInterface
,
2666 DS8Buffer3D_Release
,
2667 DS8Buffer3D_GetAllParameters
,
2668 DS8Buffer3D_GetConeAngles
,
2669 DS8Buffer3D_GetConeOrientation
,
2670 DS8Buffer3D_GetConeOutsideVolume
,
2671 DS8Buffer3D_GetMaxDistance
,
2672 DS8Buffer3D_GetMinDistance
,
2673 DS8Buffer3D_GetMode
,
2674 DS8Buffer3D_GetPosition
,
2675 DS8Buffer3D_GetVelocity
,
2676 DS8Buffer3D_SetAllParameters
,
2677 DS8Buffer3D_SetConeAngles
,
2678 DS8Buffer3D_SetConeOrientation
,
2679 DS8Buffer3D_SetConeOutsideVolume
,
2680 DS8Buffer3D_SetMaxDistance
,
2681 DS8Buffer3D_SetMinDistance
,
2682 DS8Buffer3D_SetMode
,
2683 DS8Buffer3D_SetPosition
,
2684 DS8Buffer3D_SetVelocity
2688 static HRESULT WINAPI
DS8BufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
2690 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2691 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2694 static ULONG WINAPI
DS8BufferNot_AddRef(IDirectSoundNotify
*iface
)
2696 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2699 InterlockedIncrement(&This
->all_ref
);
2700 ret
= InterlockedIncrement(&This
->not_ref
);
2701 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2706 static ULONG WINAPI
DS8BufferNot_Release(IDirectSoundNotify
*iface
)
2708 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2711 ret
= InterlockedDecrement(&This
->not_ref
);
2712 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2713 if(InterlockedDecrement(&This
->all_ref
) == 0)
2714 DS8Buffer_Destroy(This
);
2719 static HRESULT WINAPI
DS8BufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
2721 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2722 DSBPOSITIONNOTIFY
*nots
;
2726 TRACE("(%p)->(%"LONGFMT
"u, %p))\n", iface
, count
, notifications
);
2728 EnterCriticalSection(This
->crst
);
2729 hr
= DSERR_INVALIDPARAM
;
2730 if(count
&& !notifications
)
2733 hr
= IDirectSoundBuffer8_GetStatus(&This
->IDirectSoundBuffer8_iface
, &state
);
2737 hr
= DSERR_INVALIDCALL
;
2738 if((state
&DSBSTATUS_PLAYING
))
2743 HeapFree(GetProcessHeap(), 0, This
->notify
);
2752 hr
= DSERR_INVALIDPARAM
;
2753 for(i
= 0;i
< count
;++i
)
2755 if(notifications
[i
].dwOffset
>= This
->buffer
->buf_size
&&
2756 notifications
[i
].dwOffset
!= (DWORD
)DSBPN_OFFSETSTOP
)
2761 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
2764 memcpy(nots
, notifications
, count
*sizeof(*nots
));
2766 HeapFree(GetProcessHeap(), 0, This
->notify
);
2767 This
->notify
= nots
;
2768 This
->nnotify
= count
;
2774 LeaveCriticalSection(This
->crst
);
2778 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
=
2780 DS8BufferNot_QueryInterface
,
2781 DS8BufferNot_AddRef
,
2782 DS8BufferNot_Release
,
2783 DS8BufferNot_SetNotificationPositions
2787 static HRESULT WINAPI
DS8BufferProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
2789 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2790 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2793 static ULONG WINAPI
DS8BufferProp_AddRef(IKsPropertySet
*iface
)
2795 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2798 InterlockedIncrement(&This
->all_ref
);
2799 ret
= InterlockedIncrement(&This
->prop_ref
);
2800 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2805 static ULONG WINAPI
DS8BufferProp_Release(IKsPropertySet
*iface
)
2807 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2810 ret
= InterlockedDecrement(&This
->prop_ref
);
2811 TRACE("new refcount %"LONGFMT
"d\n", ret
);
2812 if(InterlockedDecrement(&This
->all_ref
) == 0)
2813 DS8Buffer_Destroy(This
);
2818 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2819 handled through secondary buffers. */
2820 static HRESULT WINAPI
DS8BufferProp_Get(IKsPropertySet
*iface
,
2821 REFGUID guidPropSet
, ULONG dwPropID
,
2822 LPVOID pInstanceData
, ULONG cbInstanceData
,
2823 LPVOID pPropData
, ULONG cbPropData
,
2826 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2827 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2829 TRACE("(%p)->(%s, %"LONGFMT
"u, %p, %"LONGFMT
"u, %p, %"LONGFMT
"u, %p)\n", iface
, debugstr_guid(guidPropSet
),
2830 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
2837 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2843 /* Not a known buffer/source property. Pass it to the listener */
2844 hr
= IKsPropertySet_Get(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2845 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
,
2852 static HRESULT WINAPI
DS8BufferProp_Set(IKsPropertySet
*iface
,
2853 REFGUID guidPropSet
, ULONG dwPropID
,
2854 LPVOID pInstanceData
, ULONG cbInstanceData
,
2855 LPVOID pPropData
, ULONG cbPropData
)
2857 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2858 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2860 TRACE("(%p)->(%s, %"LONGFMT
"u, %p, %"LONGFMT
"u, %p, %"LONGFMT
"u)\n", iface
, debugstr_guid(guidPropSet
),
2861 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
2864 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2870 /* Not a known buffer/source property. Pass it to the listener */
2871 hr
= IKsPropertySet_Set(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2872 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
,
2879 static HRESULT WINAPI
DS8BufferProp_QuerySupport(IKsPropertySet
*iface
,
2880 REFGUID guidPropSet
, ULONG dwPropID
,
2881 PULONG pTypeSupport
)
2883 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2884 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2886 TRACE("(%p)->(%s, %"LONGFMT
"u, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
2893 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2899 /* Not a known buffer/source property. Pass it to the listener */
2900 hr
= IKsPropertySet_QuerySupport(&This
->primary
->IKsPropertySet_iface
,
2901 guidPropSet
, dwPropID
, pTypeSupport
);
2907 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
=
2909 DS8BufferProp_QueryInterface
,
2910 DS8BufferProp_AddRef
,
2911 DS8BufferProp_Release
,
2914 DS8BufferProp_QuerySupport