1 /* DirectSound COM interface
3 * Copyright 2009 Maarten Lankhorst
5 * Some code taken from the original dsound-openal implementation
6 * Copyright 2007-2009 Chris Robinson
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
39 #include "wine/debug.h"
42 #include "dsound_private.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
56 #include "dsound_private.h"
58 DEFINE_GUID(CLSID_DirectSoundPrivate
,0x11ab3ec0,0x25ec,0x11d1,0xa4,0xd8,0x00,0xc0,0x4f,0xc2,0x8a,0xca);
60 DEFINE_GUID(DSPROPSETID_DirectSoundDevice
,0x84624f82,0x25ec,0x11d1,0xa4,0xd8,0x00,0xc0,0x4f,0xc2,0x8a,0xca);
62 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM
, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
63 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
65 #ifndef E_PROP_ID_UNSUPPORTED
66 #define E_PROP_ID_UNSUPPORTED ((HRESULT)0x80070490)
71 #ifndef WAVE_FORMAT_IEEE_FLOAT
72 #define WAVE_FORMAT_IEEE_FLOAT 3
75 /* TODO: when bufferlost is set, return from all calls except initialize with
78 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
;
79 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
;
80 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
;
81 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
;
83 /* Amount of buffers that have to be queued when
84 * bufferdatastatic and buffersubdata are not available */
91 /* Lock was called and unlock isn't? */
94 WAVEFORMATEXTENSIBLE format
;
98 ALenum in_type
, in_chans
;
107 static void trigger_notifies(DS8Buffer
*buf
, DWORD lastpos
, DWORD curpos
, BOOL stopping
)
110 if (lastpos
== curpos
&& !stopping
)
112 for (i
= 0; i
< buf
->nnotify
; ++i
)
114 DSBPOSITIONNOTIFY
*not = &buf
->notify
[i
];
115 HANDLE event
= not->hEventNotify
;
116 DWORD ofs
= not->dwOffset
;
118 if (ofs
== (DWORD
)DSBPN_OFFSETSTOP
)
125 /* Wraparound case */
126 if (curpos
< lastpos
)
128 if (ofs
< curpos
|| ofs
>= lastpos
)
134 if (ofs
>= lastpos
&& ofs
< curpos
)
139 static void CALLBACK
DS8Buffer_timer(UINT timerID
, UINT msg
, DWORD_PTR dwUser
,
140 DWORD_PTR dw1
, DWORD_PTR dw2
)
142 DS8Primary
*prim
= (DS8Primary
*)dwUser
;
149 EnterCriticalSection(&prim
->crst
);
150 setALContext(prim
->ctx
);
152 /* OpenAL doesn't support our lovely buffer extensions
153 * so just make sure enough buffers are queued
155 if(!prim
->ExtAL
.BufferSamplesSOFT
&& !prim
->ExtAL
.BufferSubData
&&
156 !prim
->ExtAL
.BufferDataStatic
)
158 /* FIXME: Should probably use this logic to also
159 * call trigger_notifies
161 for (i
= 0; i
< prim
->nbuffers
; ++i
)
163 DS8Buffer
*buf
= prim
->buffers
[i
];
164 ALint done
= 0, queued
= QBUFFERS
, state
= AL_PLAYING
;
167 if (buf
->buffer
->numsegs
== 1 || !buf
->isplaying
)
170 alGetSourcei(buf
->source
, AL_SOURCE_STATE
, &state
);
171 alGetSourcei(buf
->source
, AL_BUFFERS_QUEUED
, &queued
);
172 alGetSourcei(buf
->source
, AL_BUFFERS_PROCESSED
, &done
);
176 alSourceUnqueueBuffers(buf
->source
, 1, &which
);
177 while (queued
< QBUFFERS
)
179 which
= buf
->buffer
->buffers
[buf
->curidx
];
180 ofs
= buf
->curidx
*buf
->buffer
->segsize
;
181 if(buf
->curidx
< buf
->buffer
->numsegs
-1)
182 alBufferData(which
, buf
->buffer
->buf_format
,
183 buf
->buffer
->data
+ ofs
, buf
->buffer
->segsize
,
184 buf
->buffer
->format
.Format
.nSamplesPerSec
);
186 alBufferData(which
, buf
->buffer
->buf_format
,
187 buf
->buffer
->data
+ ofs
, buf
->buffer
->lastsegsize
,
188 buf
->buffer
->format
.Format
.nSamplesPerSec
);
190 alSourceQueueBuffers(buf
->source
, 1, &which
);
191 buf
->curidx
= (buf
->curidx
+1)%buf
->buffer
->numsegs
;
194 if (!buf
->curidx
&& !buf
->islooping
)
196 buf
->isplaying
= FALSE
;
200 if (state
!= AL_PLAYING
)
204 IDirectSoundBuffer8_Stop(&buf
->IDirectSoundBuffer8_iface
);
207 alSourcePlay(buf
->source
);
213 for (i
= 0; i
< prim
->nnotifies
; )
215 DS8Buffer
*buf
= prim
->notifies
[i
];
216 IDirectSoundBuffer8
*dsb
= &buf
->IDirectSoundBuffer8_iface
;
217 DWORD status
, curpos
;
220 hr
= IDirectSoundBuffer8_GetStatus(dsb
, &status
);
223 if (!(status
& DSBSTATUS_PLAYING
))
225 /* Stop will remove this buffer from list,
226 * and put another at the current position
229 IDirectSoundBuffer8_Stop(dsb
);
232 hr
= IDirectSoundBuffer8_GetCurrentPosition(dsb
, &curpos
, NULL
);
235 trigger_notifies(buf
, buf
->lastpos
, curpos
, FALSE
);
236 buf
->lastpos
= curpos
;
242 LeaveCriticalSection(&prim
->crst
);
245 static void DS8Buffer_starttimer(DS8Primary
*prim
)
248 ALint refresh
= FAKE_REFRESH_COUNT
;
249 DWORD triggertime
, res
= DS_TIME_RES
;
254 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
256 alcGetIntegerv(prim
->parent
->device
, ALC_REFRESH
, 1, &refresh
);
257 getALCError(prim
->parent
->device
);
259 triggertime
= 1000 / refresh
;
260 if(triggertime
< time
.wPeriodMin
)
261 triggertime
= time
.wPeriodMin
;
262 TRACE("Calling timer every %u ms for %i refreshes per second\n", triggertime
, refresh
);
264 if (res
< time
.wPeriodMin
)
265 res
= time
.wPeriodMin
;
266 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
267 WARN("Could not set minimum resolution, don't expect sound\n");
269 prim
->timer_res
= res
;
270 prim
->timer_id
= timeSetEvent(triggertime
, res
, DS8Buffer_timer
, (DWORD_PTR
)prim
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
273 /* Should be called with critsect held and context set.. */
274 static void DS8Buffer_addnotify(DS8Buffer
*buf
)
279 list
= buf
->primary
->notifies
;
280 for(i
= 0; i
< buf
->primary
->nnotifies
; ++i
)
284 ERR("Buffer %p already in notification list\n", buf
);
288 if(buf
->primary
->nnotifies
== buf
->primary
->sizenotifies
)
290 list
= HeapReAlloc(GetProcessHeap(), 0, list
, (buf
->primary
->nnotifies
+ 1) * sizeof(*list
));
293 buf
->primary
->sizenotifies
++;
295 list
[buf
->primary
->nnotifies
++] = buf
;
296 buf
->primary
->notifies
= list
;
299 static void DS8Buffer_removenotify(DS8Buffer
*buf
)
302 for(i
= 0; i
< buf
->primary
->nnotifies
; ++i
)
304 if(buf
== buf
->primary
->notifies
[i
])
306 buf
->primary
->notifies
[i
] =
307 buf
->primary
->notifies
[--buf
->primary
->nnotifies
];
313 static const char *get_fmtstr_PCM(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
315 out
->Format
= *format
;
316 out
->Format
.cbSize
= 0;
318 if(format
->wBitsPerSample
== 8)
320 *in_type
= AL_UNSIGNED_BYTE
;
321 switch(format
->nChannels
)
323 case 1: *in_chans
= AL_MONO
;
324 return "AL_FORMAT_MONO8";
325 case 2: *in_chans
= AL_STEREO
;
326 return "AL_FORMAT_STEREO8";
327 case 4: *in_chans
= AL_QUAD
;
328 return "AL_FORMAT_QUAD8";
329 case 6: *in_chans
= AL_5POINT1
;
330 return "AL_FORMAT_51CHN8";
331 case 7: *in_chans
= AL_6POINT1
;
332 return "AL_FORMAT_61CHN8";
333 case 8: *in_chans
= AL_7POINT1
;
334 return "AL_FORMAT_71CHN8";
338 else if(format
->wBitsPerSample
== 16)
341 switch(format
->nChannels
)
343 case 1: *in_chans
= AL_MONO
;
344 return "AL_FORMAT_MONO16";
345 case 2: *in_chans
= AL_STEREO
;
346 return "AL_FORMAT_STEREO16";
347 case 4: *in_chans
= AL_QUAD
;
348 return "AL_FORMAT_QUAD16";
349 case 6: *in_chans
= AL_5POINT1
;
350 return "AL_FORMAT_51CHN16";
351 case 7: *in_chans
= AL_6POINT1
;
352 return "AL_FORMAT_61CHN16";
353 case 8: *in_chans
= AL_7POINT1
;
354 return "AL_FORMAT_71CHN16";
358 #if 0 /* Will cause incorrect byte offsets */
359 else if(format
->wBitsPerSample
== 24 && prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
362 switch(format
->nChannels
)
364 case 1: *in_chans
= AL_MONO
;
366 case 2: *in_chans
= AL_STEREO
;
367 return "AL_STEREO32F";
368 case 4: *in_chans
= AL_QUAD
;
370 case 6: *in_chans
= AL_5POINT1
;
371 return "AL_5POINT1_32F";
372 case 7: *in_chans
= AL_6POINT1
;
373 return "AL_6POINT1_32F";
374 case 8: *in_chans
= AL_7POINT1
;
375 return "AL_7POINT1_32F";
380 else if(format
->wBitsPerSample
== 32 && prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
383 switch(format
->nChannels
)
385 case 1: *in_chans
= AL_MONO
;
387 case 2: *in_chans
= AL_STEREO
;
388 return "AL_STEREO32F";
389 case 4: *in_chans
= AL_QUAD
;
391 case 6: *in_chans
= AL_5POINT1
;
392 return "AL_5POINT1_32F";
393 case 7: *in_chans
= AL_6POINT1
;
394 return "AL_6POINT1_32F";
395 case 8: *in_chans
= AL_7POINT1
;
396 return "AL_7POINT1_32F";
401 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
402 format
->wBitsPerSample
, format
->nChannels
);
406 static const char *get_fmtstr_FLOAT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
408 out
->Format
= *format
;
409 out
->Format
.cbSize
= 0;
411 if(format
->wBitsPerSample
== 32 &&
412 (prim
->SupportedExt
[EXT_FLOAT32
] || prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
]))
415 switch(format
->nChannels
)
417 case 1: *in_chans
= AL_MONO
;
418 return "AL_FORMAT_MONO_FLOAT32";
419 case 2: *in_chans
= AL_STEREO
;
420 return "AL_FORMAT_STEREO_FLOAT32";
421 case 4: *in_chans
= AL_QUAD
;
422 return "AL_FORMAT_QUAD32";
423 case 6: *in_chans
= AL_5POINT1
;
424 return "AL_FORMAT_51CHN32";
425 case 7: *in_chans
= AL_6POINT1
;
426 return "AL_FORMAT_61CHN32";
427 case 8: *in_chans
= AL_7POINT1
;
428 return "AL_FORMAT_71CHN32";
432 #if 0 /* Will cause incorrect byte offsets */
433 else if(format
->wBitsPerSample
== 64 && prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
435 *in_type
= AL_DOUBLE
;
436 switch(format
->nChannels
)
438 case 1: *in_chans
= AL_MONO
;
440 case 2: *in_chans
= AL_STEREO
;
441 return "AL_STEREO32F";
442 case 4: *in_chans
= AL_QUAD
;
444 case 6: *in_chans
= AL_5POINT1
;
445 return "AL_5POINT1_32F";
446 case 7: *in_chans
= AL_6POINT1
;
447 return "AL_6POINT1_32F";
448 case 8: *in_chans
= AL_7POINT1
;
449 return "AL_7POINT1_32F";
455 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
456 format
->wBitsPerSample
, format
->nChannels
);
460 /* Speaker configs */
461 #define MONO SPEAKER_FRONT_CENTER
462 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
463 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
464 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
465 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
466 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
467 #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)
469 static const char *get_fmtstr_EXT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
, ALenum
*in_chans
, ALenum
*in_type
)
471 *out
= *(const WAVEFORMATEXTENSIBLE
*)format
;
472 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
474 if(!out
->Samples
.wValidBitsPerSample
)
475 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
476 else if(out
->Samples
.wValidBitsPerSample
!= out
->Format
.wBitsPerSample
)
478 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
482 if(out
->dwChannelMask
!= MONO
&& out
->dwChannelMask
!= STEREO
&&
483 !prim
->SupportedExt
[EXT_MCFORMATS
] && !prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
485 WARN("Multi-channel not available\n");
489 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
491 if(out
->Samples
.wValidBitsPerSample
== 8)
493 *in_type
= AL_UNSIGNED_BYTE
;
494 switch(out
->dwChannelMask
)
496 case MONO
: *in_chans
= AL_MONO
;
497 return "AL_FORMAT_MONO8";
498 case STEREO
: *in_chans
= AL_STEREO
;
499 return "AL_FORMAT_STEREO8";
500 case REAR
: *in_chans
= AL_REAR
;
501 return "AL_FORMAT_REAR8";
502 case QUAD
: *in_chans
= AL_QUAD
;
503 return "AL_FORMAT_QUAD8";
504 case X5DOT1
: *in_chans
= AL_5POINT1
;
505 return "AL_FORMAT_51CHN8";
506 case X6DOT1
: *in_chans
= AL_6POINT1
;
507 return "AL_FORMAT_61CHN8";
508 case X7DOT1
: *in_chans
= AL_7POINT1
;
509 return "AL_FORMAT_71CHN8";
513 else if(out
->Samples
.wValidBitsPerSample
== 16)
516 switch(out
->dwChannelMask
)
518 case MONO
: *in_chans
= AL_MONO
;
519 return "AL_FORMAT_MONO16";
520 case STEREO
: *in_chans
= AL_STEREO
;
521 return "AL_FORMAT_STEREO16";
522 case REAR
: *in_chans
= AL_REAR
;
523 return "AL_FORMAT_REAR16";
524 case QUAD
: *in_chans
= AL_QUAD
;
525 return "AL_FORMAT_QUAD16";
526 case X5DOT1
: *in_chans
= AL_5POINT1
;
527 return "AL_FORMAT_51CHN16";
528 case X6DOT1
: *in_chans
= AL_6POINT1
;
529 return "AL_FORMAT_61CHN16";
530 case X7DOT1
: *in_chans
= AL_7POINT1
;
531 return "AL_FORMAT_71CHN16";
536 else if(out
->Samples
.wValidBitsPerSample
== 24 &&
537 prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
540 switch(out
->dwChannelMask
)
542 case MONO
: *in_chans
= AL_MONO
;
544 case STEREO
: *in_chans
= AL_STEREO
;
545 return "AL_STEREO32F";
546 case REAR
: *in_chans
= AL_REAR
;
548 case QUAD
: *in_chans
= AL_QUAD
;
550 case X5DOT1
: *in_chans
= AL_5POINT1
;
551 return "AL_5POINT1_32F";
552 case X6DOT1
: *in_chans
= AL_6POINT1
;
553 return "AL_6POINT1_32F";
554 case X7DOT1
: *in_chans
= AL_7POINT1
;
555 return "AL_7POINT1_32F";
560 else if(out
->Samples
.wValidBitsPerSample
== 32 &&
561 prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
564 switch(out
->dwChannelMask
)
566 case MONO
: *in_chans
= AL_MONO
;
568 case STEREO
: *in_chans
= AL_STEREO
;
569 return "AL_STEREO32F";
570 case REAR
: *in_chans
= AL_REAR
;
572 case QUAD
: *in_chans
= AL_QUAD
;
574 case X5DOT1
: *in_chans
= AL_5POINT1
;
575 return "AL_5POINT1_32F";
576 case X6DOT1
: *in_chans
= AL_6POINT1
;
577 return "AL_6POINT1_32F";
578 case X7DOT1
: *in_chans
= AL_7POINT1
;
579 return "AL_7POINT1_32F";
584 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#x)\n",
585 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
588 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
589 (prim
->SupportedExt
[EXT_FLOAT32
] || prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
]))
591 if(out
->Samples
.wValidBitsPerSample
== 32)
594 switch(out
->dwChannelMask
)
596 case MONO
: *in_chans
= AL_MONO
;
597 return "AL_FORMAT_MONO_FLOAT32";
598 case STEREO
: *in_chans
= AL_STEREO
;
599 return "AL_FORMAT_STEREO_FLOAT32";
600 case REAR
: *in_chans
= AL_REAR
;
601 return "AL_FORMAT_REAR32";
602 case QUAD
: *in_chans
= AL_QUAD
;
603 return "AL_FORMAT_QUAD32";
604 case X5DOT1
: *in_chans
= AL_5POINT1
;
605 return "AL_FORMAT_51CHN32";
606 case X6DOT1
: *in_chans
= AL_6POINT1
;
607 return "AL_FORMAT_61CHN32";
608 case X7DOT1
: *in_chans
= AL_7POINT1
;
609 return "AL_FORMAT_71CHN32";
614 else if(out
->Samples
.wValidBitsPerSample
== 64 &&
615 prim
->SupportedExt
[SOFT_BUFFER_SAMPLES
])
617 *in_type
= AL_DOUBLE
;
618 switch(out
->dwChannelMask
)
620 case MONO
: *in_chans
= AL_MONO
;
622 case STEREO
: *in_chans
= AL_STEREO
;
623 return "AL_STEREO32F";
624 case REAR
: *in_chans
= AL_REAR
;
626 case QUAD
: *in_chans
= AL_QUAD
;
628 case X5DOT1
: *in_chans
= AL_5POINT1
;
629 return "AL_5POINT1_32F";
630 case X6DOT1
: *in_chans
= AL_6POINT1
;
631 return "AL_6POINT1_32F";
632 case X7DOT1
: *in_chans
= AL_7POINT1
;
633 return "AL_7POINT1_32F";
640 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
644 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#x)\n",
645 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
648 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
649 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
653 static void DS8Data_Release(DS8Data
*This
);
654 static HRESULT
DS8Data_Create(DS8Data
**ppv
, const DSBUFFERDESC
*desc
, DS8Primary
*prim
)
656 HRESULT hr
= DSERR_INVALIDPARAM
;
657 const WAVEFORMATEX
*format
;
658 const char *fmt_str
= NULL
;
661 format
= desc
->lpwfxFormat
;
662 TRACE("Requested buffer format:\n"
663 " FormatTag = 0x%04x\n"
665 " SamplesPerSec = %u\n"
666 " AvgBytesPerSec = %u\n"
668 " BitsPerSample = %d\n",
669 format
->wFormatTag
, format
->nChannels
,
670 format
->nSamplesPerSec
, format
->nAvgBytesPerSec
,
671 format
->nBlockAlign
, format
->wBitsPerSample
);
673 if(format
->nBlockAlign
== 0)
675 WARN("Invalid BlockAlign specified\n");
676 return DSERR_INVALIDPARAM
;
679 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
680 * will need the EAX-RAM extension. Currently, we just tell the app it
681 * gets what it wanted. */
682 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
));
684 return E_OUTOFMEMORY
;
687 pBuffer
->dsbflags
= desc
->dwFlags
;
688 if((pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
)) == (DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
))
690 WARN("Hardware and software location requested\n");
693 if(!(pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCDEFER
)))
694 pBuffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
696 pBuffer
->buf_size
= desc
->dwBufferBytes
+ format
->nBlockAlign
- 1;
697 pBuffer
->buf_size
-= pBuffer
->buf_size
%format
->nBlockAlign
;
699 hr
= DSERR_BUFFERTOOSMALL
;
700 if(pBuffer
->buf_size
< DSBSIZE_MIN
)
703 hr
= DSERR_INVALIDPARAM
;
704 if(pBuffer
->buf_size
> DSBSIZE_MAX
)
707 pBuffer
->numsegs
= 1;
708 pBuffer
->segsize
= pBuffer
->buf_size
;
709 pBuffer
->lastsegsize
= pBuffer
->buf_size
;
711 if(!(pBuffer
->dsbflags
&DSBCAPS_STATIC
) && !prim
->ExtAL
.BufferSubData
&&
712 !prim
->ExtAL
.BufferSamplesSOFT
&& !prim
->ExtAL
.BufferDataStatic
)
714 ALCint refresh
= FAKE_REFRESH_COUNT
;
717 alcGetIntegerv(prim
->parent
->device
, ALC_REFRESH
, 1, &refresh
);
718 getALCError(prim
->parent
->device
);
720 newSize
= format
->nAvgBytesPerSec
/refresh
+ format
->nBlockAlign
- 1;
721 newSize
-= newSize
%format
->nBlockAlign
;
723 /* Make sure enough buffers are available */
724 if(newSize
> pBuffer
->buf_size
/(QBUFFERS
+2))
725 ERR("Buffer segments too large to stream (%u for %u)!\n",
726 newSize
, pBuffer
->buf_size
);
729 pBuffer
->numsegs
= pBuffer
->buf_size
/newSize
;
730 pBuffer
->segsize
= newSize
;
731 pBuffer
->lastsegsize
= pBuffer
->buf_size
- (newSize
*(pBuffer
->numsegs
-1));
732 TRACE("New streaming buffer (%u chunks, %u : %u sizes)\n",
733 pBuffer
->numsegs
, pBuffer
->segsize
, pBuffer
->lastsegsize
);
737 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
738 fmt_str
= get_fmtstr_PCM(prim
, format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
739 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
740 fmt_str
= get_fmtstr_FLOAT(prim
, format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
741 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
743 const WAVEFORMATEXTENSIBLE
*wfe
;
745 hr
= DSERR_CONTROLUNAVAIL
;
746 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
747 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
750 wfe
= (const WAVEFORMATEXTENSIBLE
*)format
;
751 TRACE("Extensible values:\n"
753 " ChannelMask = %#x\n"
755 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
756 debugstr_guid(&wfe
->SubFormat
));
758 hr
= DSERR_INVALIDCALL
;
759 fmt_str
= get_fmtstr_EXT(prim
, format
, &pBuffer
->format
, &pBuffer
->in_chans
, &pBuffer
->in_type
);
762 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
767 pBuffer
->buf_format
= alGetEnumValue(fmt_str
);
768 if(alGetError() != AL_NO_ERROR
|| pBuffer
->buf_format
== 0 ||
769 pBuffer
->buf_format
== -1)
771 WARN("Could not get OpenAL format from %s\n", fmt_str
);
776 pBuffer
->buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
->buffers
)*pBuffer
->numsegs
);
777 pBuffer
->data
= HeapAlloc(GetProcessHeap(), 0, pBuffer
->buf_size
);
778 if(!pBuffer
->buffers
|| !pBuffer
->data
)
781 alGenBuffers(pBuffer
->numsegs
, pBuffer
->buffers
);
788 DS8Data_Release(pBuffer
);
792 static void DS8Data_AddRef(DS8Data
*data
)
794 InterlockedIncrement(&data
->ref
);
797 /* This function is always called with the device lock held */
798 static void DS8Data_Release(DS8Data
*This
)
800 if(InterlockedDecrement(&This
->ref
)) return;
802 TRACE("Deleting %p\n", This
);
803 if (This
->buffers
&& This
->buffers
[0])
805 alDeleteBuffers(This
->numsegs
, This
->buffers
);
808 HeapFree(GetProcessHeap(), 0, This
->buffers
);
809 HeapFree(GetProcessHeap(), 0, This
->data
);
810 HeapFree(GetProcessHeap(), 0, This
);
813 HRESULT
DS8Buffer_Create(DS8Buffer
**ppv
, DS8Primary
*parent
, DS8Buffer
*orig
)
815 HRESULT hr
= DSERR_OUTOFMEMORY
;
820 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
823 This
->IDirectSoundBuffer8_iface
.lpVtbl
= (IDirectSoundBuffer8Vtbl
*)&DS8Buffer_Vtbl
;
824 This
->IDirectSound3DBuffer_iface
.lpVtbl
= (IDirectSound3DBufferVtbl
*)&DS8Buffer3d_Vtbl
;
825 This
->IDirectSoundNotify_iface
.lpVtbl
= (IDirectSoundNotifyVtbl
*)&DS8BufferNot_Vtbl
;
826 This
->IKsPropertySet_iface
.lpVtbl
= (IKsPropertySetVtbl
*)&DS8BufferProp_Vtbl
;
828 This
->primary
= parent
;
829 This
->ctx
= parent
->ctx
;
830 This
->ExtAL
= &parent
->ExtAL
;
831 This
->crst
= &parent
->crst
;
832 This
->ref
= This
->all_ref
= 1;
836 This
->buffer
= orig
->buffer
;
837 DS8Data_AddRef(This
->buffer
);
840 /* Append to buffer list */
841 bufs
= parent
->buffers
;
842 if(parent
->nbuffers
== parent
->sizebuffers
)
844 bufs
= HeapReAlloc(GetProcessHeap(), 0, bufs
, sizeof(*bufs
)*(1+parent
->nbuffers
));
846 parent
->sizebuffers
++;
848 parent
->buffers
= bufs
;
849 bufs
[parent
->nbuffers
++] = This
;
851 /* Disable until initialized.. */
852 This
->ds3dmode
= DS3DMODE_DISABLE
;
858 DS8Buffer_Destroy(This
);
862 void DS8Buffer_Destroy(DS8Buffer
*This
)
865 TRACE("Destroying %p\n", This
);
867 DS8Buffer_removenotify(This
);
869 /* Remove from list, if in list */
870 for(idx
= 0;idx
< This
->primary
->nbuffers
;++idx
)
872 if(This
->primary
->buffers
[idx
] == This
)
874 This
->primary
->buffers
[idx
] = This
->primary
->buffers
[This
->primary
->nbuffers
-1];
875 This
->primary
->nbuffers
--;
879 setALContext(This
->ctx
);
884 alSourceStop(This
->source
);
885 alSourcei(This
->source
, AL_BUFFER
, 0);
888 sources
= This
->primary
->sources
;
889 if(This
->primary
->nsources
== This
->primary
->sizesources
)
891 sources
= HeapReAlloc(GetProcessHeap(), 0, sources
, sizeof(*sources
)*(1+This
->primary
->nsources
));
893 alDeleteSources(1, &This
->source
);
895 This
->primary
->sizesources
++;
899 sources
[This
->primary
->nsources
++] = This
->source
;
900 This
->primary
->sources
= sources
;
903 HeapFree(GetProcessHeap(), 0, This
->notify
);
906 DS8Data_Release(This
->buffer
);
908 HeapFree(GetProcessHeap(), 0, This
);
911 static inline DS8Buffer
*impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8
*iface
)
913 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer8_iface
);
916 static HRESULT WINAPI
DS8Buffer_QueryInterface(IDirectSoundBuffer8
*iface
, REFIID riid
, void **ppv
)
918 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
920 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
923 if(IsEqualIID(riid
, &IID_IUnknown
) ||
924 IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
925 *ppv
= &This
->IDirectSoundBuffer8_iface
;
926 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer8
))
928 if(This
->primary
->parent
->is_8
)
929 *ppv
= &This
->IDirectSoundBuffer8_iface
;
931 else if(IsEqualIID(riid
, &IID_IDirectSound3DBuffer
))
933 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
934 *ppv
= &This
->IDirectSound3DBuffer_iface
;
936 else if(IsEqualIID(riid
, &IID_IDirectSoundNotify
))
938 if((This
->buffer
->dsbflags
&DSBCAPS_CTRLPOSITIONNOTIFY
))
939 *ppv
= &This
->IDirectSoundNotify_iface
;
941 else if(IsEqualIID(riid
, &IID_IKsPropertySet
))
942 *ppv
= &This
->IKsPropertySet_iface
;
944 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
948 IUnknown_AddRef((IUnknown
*)*ppv
);
952 return E_NOINTERFACE
;
955 static ULONG WINAPI
DS8Buffer_AddRef(IDirectSoundBuffer8
*iface
)
957 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
960 InterlockedIncrement(&This
->all_ref
);
961 ret
= InterlockedIncrement(&This
->ref
);
962 TRACE("new refcount %d\n", ret
);
967 static ULONG WINAPI
DS8Buffer_Release(IDirectSoundBuffer8
*iface
)
969 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
972 ret
= InterlockedDecrement(&This
->ref
);
973 TRACE("new refcount %d\n", ret
);
974 if(InterlockedDecrement(&This
->all_ref
) == 0)
975 DS8Buffer_Destroy(This
);
980 static HRESULT WINAPI
DS8Buffer_GetCaps(IDirectSoundBuffer8
*iface
, DSBCAPS
*caps
)
982 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
984 TRACE("(%p)->(%p)\n", iface
, caps
);
986 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
988 WARN("Invalid DSBCAPS (%p, %u)\n", caps
, (caps
? caps
->dwSize
: 0));
989 return DSERR_INVALIDPARAM
;
992 caps
->dwFlags
= This
->buffer
->dsbflags
;
993 caps
->dwBufferBytes
= This
->buffer
->buf_size
;
994 caps
->dwUnlockTransferRate
= 4096;
995 caps
->dwPlayCpuOverhead
= 0;
999 static HRESULT WINAPI
DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD
*playpos
, DWORD
*curpos
)
1001 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1002 WAVEFORMATEX
*format
= &This
->buffer
->format
.Format
;
1003 UINT writecursor
, pos
;
1005 TRACE("(%p)->(%p, %p)\n", iface
, playpos
, curpos
);
1007 EnterCriticalSection(This
->crst
);
1008 setALContext(This
->ctx
);
1010 if(This
->buffer
->numsegs
> 1)
1012 ALint queued
= QBUFFERS
;
1013 alGetSourcei(This
->source
, AL_BUFFERS_QUEUED
, &queued
);
1016 pos
= (This
->curidx
+This
->buffer
->numsegs
-queued
)%This
->buffer
->numsegs
;
1017 pos
*= This
->buffer
->segsize
;
1018 writecursor
= This
->curidx
* This
->buffer
->segsize
;
1020 else if(This
->ExtAL
->BufferSubData
|| This
->ExtAL
->BufferSamplesSOFT
)
1022 ALint rwpos
[2] = { 0, 0 };
1024 alGetSourceiv(This
->source
, AL_BYTE_RW_OFFSETS_SOFT
, rwpos
);
1028 writecursor
= rwpos
[1];
1035 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
1036 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
1040 if(status
== AL_PLAYING
)
1042 writecursor
= format
->nSamplesPerSec
/ 100;
1043 writecursor
*= format
->nBlockAlign
;
1047 writecursor
= (writecursor
+ pos
) % This
->buffer
->buf_size
;
1049 TRACE("%p Play pos = %u, write pos = %u\n", This
, pos
, writecursor
);
1050 if(pos
>= This
->buffer
->buf_size
)
1052 ERR("playpos >= buf_size\n");
1053 pos
%= This
->buffer
->buf_size
;
1055 if(writecursor
>= This
->buffer
->buf_size
)
1057 ERR("writepos >= buf_size\n");
1058 writecursor
%= This
->buffer
->buf_size
;
1061 if(playpos
) *playpos
= pos
;
1062 if(curpos
) *curpos
= writecursor
;
1065 LeaveCriticalSection(This
->crst
);
1070 static HRESULT WINAPI
DS8Buffer_GetFormat(IDirectSoundBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
1072 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1076 TRACE("(%p)->(%p, %u, %p)\n", iface
, wfx
, allocated
, written
);
1078 if(!wfx
&& !written
)
1080 WARN("Cannot report format or format size\n");
1081 return DSERR_INVALIDPARAM
;
1084 EnterCriticalSection(This
->crst
);
1085 size
= sizeof(This
->buffer
->format
.Format
) + This
->buffer
->format
.Format
.cbSize
;
1088 if(allocated
< size
)
1089 hr
= DSERR_INVALIDPARAM
;
1091 memcpy(wfx
, &This
->buffer
->format
.Format
, size
);
1095 LeaveCriticalSection(This
->crst
);
1100 static HRESULT WINAPI
DS8Buffer_GetVolume(IDirectSoundBuffer8
*iface
, LONG
*vol
)
1102 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1105 TRACE("(%p)->(%p)\n", iface
, vol
);
1109 WARN("Invalid pointer\n");
1110 return DSERR_INVALIDPARAM
;
1113 EnterCriticalSection(This
->crst
);
1115 hr
= DSERR_CONTROLUNAVAIL
;
1116 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1117 WARN("Volume control not set\n");
1120 ALfloat gain
= 1.0f
;
1122 setALContext(This
->ctx
);
1123 alGetSourcef(This
->source
, AL_GAIN
, &gain
);
1127 *vol
= gain_to_mB(gain
);
1128 *vol
= min(*vol
, DSBVOLUME_MAX
);
1129 *vol
= max(*vol
, DSBVOLUME_MIN
);
1134 LeaveCriticalSection(This
->crst
);
1138 static HRESULT WINAPI
DS8Buffer_GetPan(IDirectSoundBuffer8
*iface
, LONG
*pan
)
1140 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1143 TRACE("(%p)->(%p)\n", iface
, pan
);
1147 WARN("Invalid pointer\n");
1148 return DSERR_INVALIDPARAM
;
1151 EnterCriticalSection(This
->crst
);
1153 hr
= DSERR_CONTROLUNAVAIL
;
1154 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1155 WARN("Panning control not set\n");
1160 setALContext(This
->ctx
);
1161 alGetSourcefv(This
->source
, AL_POSITION
, pos
);
1165 *pan
= (LONG
)((pos
[0]+1.0) * (DSBPAN_RIGHT
-DSBPAN_LEFT
) / 2.0 + 0.5) + DSBPAN_LEFT
;
1166 *pan
= min(*pan
, DSBPAN_RIGHT
);
1167 *pan
= max(*pan
, DSBPAN_LEFT
);
1172 LeaveCriticalSection(This
->crst
);
1176 static HRESULT WINAPI
DS8Buffer_GetFrequency(IDirectSoundBuffer8
*iface
, DWORD
*freq
)
1178 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1181 TRACE("(%p)->(%p)\n", iface
, freq
);
1185 WARN("Invalid pointer\n");
1186 return DSERR_INVALIDPARAM
;
1189 EnterCriticalSection(This
->crst
);
1191 hr
= DSERR_CONTROLUNAVAIL
;
1192 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1193 WARN("Frequency control not set\n");
1196 ALfloat pitch
= 1.0f
;
1198 setALContext(This
->ctx
);
1199 alGetSourcefv(This
->source
, AL_PITCH
, &pitch
);
1203 *freq
= (DWORD
)(This
->buffer
->format
.Format
.nSamplesPerSec
* pitch
);
1208 LeaveCriticalSection(This
->crst
);
1212 static HRESULT WINAPI
DS8Buffer_GetStatus(IDirectSoundBuffer8
*iface
, DWORD
*status
)
1214 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1215 ALint state
, looping
;
1217 TRACE("(%p)->(%p)\n", iface
, status
);
1221 WARN("Invalid pointer\n");
1222 return DSERR_INVALIDPARAM
;
1225 EnterCriticalSection(This
->crst
);
1227 setALContext(This
->ctx
);
1228 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1229 looping
= This
->islooping
;
1230 if(This
->buffer
->numsegs
== 1)
1231 alGetSourcei(This
->source
, AL_LOOPING
, &looping
);
1232 else if(state
!= AL_PLAYING
)
1233 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1238 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1240 if((This
->buffer
->dsbflags
&DSBCAPS_LOCSOFTWARE
))
1241 *status
|= DSBSTATUS_LOCSOFTWARE
;
1242 else if((This
->buffer
->dsbflags
&DSBCAPS_LOCHARDWARE
))
1243 *status
|= DSBSTATUS_LOCHARDWARE
;
1245 if(state
== AL_PLAYING
)
1246 *status
|= DSBSTATUS_PLAYING
| (looping
? DSBSTATUS_LOOPING
: 0);
1248 LeaveCriticalSection(This
->crst
);
1253 static HRESULT WINAPI
DS8Buffer_Initialize(IDirectSoundBuffer8
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
1255 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1256 DS3DBUFFER
*ds3dbuffer
;
1259 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
1261 EnterCriticalSection(This
->crst
);
1262 setALContext(This
->ctx
);
1264 hr
= DSERR_ALREADYINITIALIZED
;
1270 hr
= DSERR_INVALIDPARAM
;
1273 WARN("Missing DSound buffer description\n");
1276 if(!desc
->lpwfxFormat
)
1278 WARN("Missing buffer format (%p)\n", This
);
1281 if((desc
->dwFlags
&DSBCAPS_CTRL3D
) && desc
->lpwfxFormat
->nChannels
!= 1)
1283 if(This
->primary
->parent
->is_8
)
1285 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
1287 WARN("Can't create multi-channel 3D buffers\n");
1290 ERR("Multi-channel 3D sounds are not spatialized\n");
1293 hr
= DS8Data_Create(&This
->buffer
, desc
, This
->primary
);
1298 DS8Data
*buf
= This
->buffer
;
1300 if(buf
->in_type
== AL_UNSIGNED_BYTE
)
1301 memset(buf
->data
, 0x80, buf
->buf_size
);
1303 memset(buf
->data
, 0x00, buf
->buf_size
);
1305 if(This
->ExtAL
->BufferDataStatic
)
1306 This
->ExtAL
->BufferDataStatic(buf
->buffers
[0], buf
->buf_format
,
1307 buf
->data
, buf
->buf_size
,
1308 buf
->format
.Format
.nSamplesPerSec
);
1309 else if(This
->ExtAL
->BufferSamplesSOFT
)
1310 This
->ExtAL
->BufferSamplesSOFT(buf
->buffers
[0],
1311 buf
->format
.Format
.nSamplesPerSec
, buf
->buf_format
,
1312 buf
->buf_size
/buf
->format
.Format
.nBlockAlign
,
1313 buf
->in_chans
, buf
->in_type
, buf
->data
);
1314 else if(This
->ExtAL
->BufferSubData
)
1315 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1316 buf
->data
, buf
->buf_size
,
1317 buf
->format
.Format
.nSamplesPerSec
);
1323 if(This
->primary
->nsources
)
1325 This
->source
= This
->primary
->sources
[--This
->primary
->nsources
];
1326 alSourcef(This
->source
, AL_GAIN
, 1.0f
);
1327 alSourcef(This
->source
, AL_PITCH
, 1.0f
);
1332 alGenSources(1, &This
->source
);
1333 if(alGetError() != AL_NO_ERROR
)
1337 ds3dbuffer
= &This
->ds3dbuffer
;
1338 ds3dbuffer
->dwSize
= sizeof(*ds3dbuffer
);
1339 ds3dbuffer
->vPosition
.x
= 0.0;
1340 ds3dbuffer
->vPosition
.y
= 0.0;
1341 ds3dbuffer
->vPosition
.z
= 0.0;
1342 ds3dbuffer
->vVelocity
.x
= 0.0;
1343 ds3dbuffer
->vVelocity
.y
= 0.0;
1344 ds3dbuffer
->vVelocity
.z
= 0.0;
1345 ds3dbuffer
->dwInsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1346 ds3dbuffer
->dwOutsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1347 ds3dbuffer
->vConeOrientation
.x
= 0.0;
1348 ds3dbuffer
->vConeOrientation
.y
= 0.0;
1349 ds3dbuffer
->vConeOrientation
.z
= 1.0;
1350 ds3dbuffer
->lConeOutsideVolume
= DS3D_DEFAULTCONEOUTSIDEVOLUME
;
1351 ds3dbuffer
->flMinDistance
= DS3D_DEFAULTMINDISTANCE
;
1352 ds3dbuffer
->flMaxDistance
= DS3D_DEFAULTMAXDISTANCE
;
1353 ds3dbuffer
->dwMode
= DS3DMODE_NORMAL
;
1355 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
1357 if(This
->primary
->auxslot
!= 0)
1359 alSource3i(This
->source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1363 hr
= IDirectSound3DBuffer_SetAllParameters(&This
->IDirectSound3DBuffer_iface
, ds3dbuffer
, DS3D_IMMEDIATE
);
1366 ERR("SetAllParameters failed\n");
1372 ALuint source
= This
->source
;
1374 if(This
->primary
->auxslot
!= 0)
1376 /* Simple hack to make reverb affect non-3D sounds too */
1377 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, AL_FILTER_NULL
);
1378 /*alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);*/
1381 /* Non-3D sources aren't distance attenuated */
1382 This
->ds3dmode
= DS3DMODE_DISABLE
;
1383 alSource3f(source
, AL_POSITION
, 0.0f
, 1.0f
, 0.0f
);
1384 alSource3f(source
, AL_VELOCITY
, 0.0f
, 0.0f
, 0.0f
);
1385 alSource3f(source
, AL_DIRECTION
, 0.0f
, 0.0f
, 0.0f
);
1386 alSourcef(source
, AL_CONE_OUTER_GAIN
, 1.0f
);
1387 alSourcef(source
, AL_REFERENCE_DISTANCE
, 1.0f
);
1388 alSourcef(source
, AL_MAX_DISTANCE
, 1000.0f
);
1389 alSourcef(source
, AL_ROLLOFF_FACTOR
, 0.0f
);
1390 alSourcei(source
, AL_CONE_INNER_ANGLE
, 360);
1391 alSourcei(source
, AL_CONE_OUTER_ANGLE
, 360);
1392 alSourcei(source
, AL_SOURCE_RELATIVE
, AL_TRUE
);
1399 LeaveCriticalSection(This
->crst
);
1404 static HRESULT WINAPI
DS8Buffer_Lock(IDirectSoundBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1406 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1410 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, 0x%x)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1414 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
1415 return DSERR_INVALIDPARAM
;
1418 EnterCriticalSection(This
->crst
);
1419 setALContext(This
->ctx
);
1423 if(ptr2
) *ptr2
= NULL
;
1426 hr
= DSERR_INVALIDPARAM
;
1427 if((flags
&DSBLOCK_FROMWRITECURSOR
))
1428 DS8Buffer_GetCurrentPosition(iface
, NULL
, &ofs
);
1429 else if(ofs
>= This
->buffer
->buf_size
)
1431 WARN("Invalid ofs %u\n", ofs
);
1434 if((flags
&DSBLOCK_ENTIREBUFFER
))
1435 bytes
= This
->buffer
->buf_size
;
1436 else if(bytes
> This
->buffer
->buf_size
)
1438 WARN("Invalid size %u\n", bytes
);
1442 *ptr1
= This
->buffer
->data
+ ofs
;
1443 if(ofs
+bytes
>= This
->buffer
->buf_size
)
1445 *len1
= This
->buffer
->buf_size
- ofs
;
1446 remain
= bytes
- *len1
;
1454 This
->buffer
->locked
= TRUE
;
1456 if(ptr2
&& len2
&& remain
)
1458 *ptr2
= This
->buffer
->data
;
1465 LeaveCriticalSection(This
->crst
);
1469 static HRESULT WINAPI
DS8Buffer_Play(IDirectSoundBuffer8
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1471 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1472 ALint type
, state
= AL_STOPPED
;
1476 TRACE("%p\n", This
);
1478 EnterCriticalSection(This
->crst
);
1479 setALContext(This
->ctx
);
1481 hr
= DSERR_BUFFERLOST
;
1482 if(This
->bufferlost
)
1484 WARN("Buffer %p lost\n", This
);
1488 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1490 if(!(This
->buffer
->dsbflags
&(DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCSOFTWARE
)))
1492 if(flags
& DSBPLAY_LOCSOFTWARE
)
1493 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1495 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1500 ERR("Invalid priority set for non-deferred buffer %p, %u!\n", This
->buffer
, prio
);
1501 hr
= DSERR_INVALIDPARAM
;
1505 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1506 if(This
->buffer
->numsegs
> 1)
1508 This
->islooping
= !!(flags
&DSBPLAY_LOOPING
);
1509 if(state
!= AL_PLAYING
&& This
->isplaying
)
1514 alGetSourcei(This
->source
, AL_SOURCE_TYPE
, &type
);
1515 alSourcei(This
->source
, AL_LOOPING
, (flags
&DSBPLAY_LOOPING
) ? AL_TRUE
: AL_FALSE
);
1520 if(state
== AL_PLAYING
)
1523 /* alSourceQueueBuffers will implicitly set type to streaming */
1524 if(This
->buffer
->numsegs
== 1)
1526 if(type
!= AL_STATIC
)
1527 alSourcei(This
->source
, AL_BUFFER
, This
->buffer
->buffers
[0]);
1528 alSourcePlay(This
->source
);
1530 if(alGetError() != AL_NO_ERROR
)
1532 ERR("Couldn't start source\n");
1533 This
->curidx
= (This
->buffer
->numsegs
-1+This
->curidx
)%This
->buffer
->numsegs
;
1534 alSourcei(This
->source
, AL_BUFFER
, 0);
1539 This
->isplaying
= TRUE
;
1543 DS8Buffer_addnotify(This
);
1544 DS8Buffer_starttimer(This
->primary
);
1546 else if(This
->buffer
->numsegs
> 1)
1547 DS8Buffer_starttimer(This
->primary
);
1551 LeaveCriticalSection(This
->crst
);
1555 static HRESULT WINAPI
DS8Buffer_SetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD pos
)
1557 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1559 TRACE("%p\n", This
);
1561 EnterCriticalSection(This
->crst
);
1562 setALContext(This
->ctx
);
1564 hr
= DSERR_INVALIDPARAM
;
1565 if(pos
>= This
->buffer
->buf_size
)
1568 if(This
->buffer
->numsegs
> 1)
1570 DS8Data
*buf
= This
->buffer
;
1571 This
->curidx
= pos
/buf
->segsize
;
1572 if(This
->curidx
>= buf
->numsegs
)
1573 This
->curidx
= buf
->numsegs
- 1;
1576 alSourceStop(This
->source
);
1577 alSourcei(This
->source
, AL_BUFFER
, 0);
1582 alSourcei(This
->source
, AL_BYTE_OFFSET
, pos
);
1583 This
->lastpos
= pos
;
1588 LeaveCriticalSection(This
->crst
);
1592 static HRESULT WINAPI
DS8Buffer_SetFormat(IDirectSoundBuffer8
*iface
, const WAVEFORMATEX
*wfx
)
1594 /* This call only works on primary buffers */
1595 WARN("(%p)->(%p)\n", iface
, wfx
);
1596 return DSERR_INVALIDCALL
;
1599 static HRESULT WINAPI
DS8Buffer_SetVolume(IDirectSoundBuffer8
*iface
, LONG vol
)
1601 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1604 TRACE("(%p)->(%d)\n", iface
, vol
);
1606 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
1608 WARN("Invalid volume (%d)\n", vol
);
1609 return DSERR_INVALIDPARAM
;
1612 EnterCriticalSection(This
->crst
);
1613 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1614 hr
= DSERR_CONTROLUNAVAIL
;
1617 ALfloat fvol
= mB_to_gain(vol
);
1618 setALContext(This
->ctx
);
1619 alSourcef(This
->source
, AL_GAIN
, fvol
);
1622 LeaveCriticalSection(This
->crst
);
1627 static HRESULT WINAPI
DS8Buffer_SetPan(IDirectSoundBuffer8
*iface
, LONG pan
)
1629 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1632 TRACE("(%p)->(%d)\n", iface
, pan
);
1634 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
1636 WARN("invalid parameter: pan = %d\n", pan
);
1637 return DSERR_INVALIDPARAM
;
1640 EnterCriticalSection(This
->crst
);
1641 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1642 hr
= DSERR_CONTROLUNAVAIL
;
1646 pos
[0] = (pan
-DSBPAN_LEFT
) * 2.0 / (ALfloat
)(DSBPAN_RIGHT
-DSBPAN_LEFT
) - 1.0;
1647 /* NOTE: Strict movement along the X plane can cause the sound to jump
1648 * between left and right sharply. Using a curved path helps smooth it
1650 pos
[1] = sqrt(1.0 - pos
[0]*pos
[0]);
1653 setALContext(This
->ctx
);
1654 alSourcefv(This
->source
, AL_POSITION
, pos
);
1658 if(pan
!= 0 && This
->buffer
->format
.Format
.nChannels
> 1)
1659 FIXME("Panning for multi-channel buffers is not supported\n");
1661 LeaveCriticalSection(This
->crst
);
1666 static HRESULT WINAPI
DS8Buffer_SetFrequency(IDirectSoundBuffer8
*iface
, DWORD freq
)
1668 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1671 TRACE("(%p)->(%u)\n", iface
, freq
);
1673 if(freq
< DSBFREQUENCY_MIN
|| freq
> DSBFREQUENCY_MAX
)
1675 WARN("invalid parameter: freq = %d\n", freq
);
1676 return DSERR_INVALIDPARAM
;
1679 EnterCriticalSection(This
->crst
);
1680 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1681 hr
= DSERR_CONTROLUNAVAIL
;
1684 ALfloat pitch
= 1.0f
;
1685 if(freq
!= DSBFREQUENCY_ORIGINAL
)
1686 pitch
= freq
/ (ALfloat
)This
->buffer
->format
.Format
.nSamplesPerSec
;
1688 setALContext(This
->ctx
);
1689 alSourcef(This
->source
, AL_PITCH
, pitch
);
1693 LeaveCriticalSection(This
->crst
);
1697 static HRESULT WINAPI
DS8Buffer_Stop(IDirectSoundBuffer8
*iface
)
1699 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1702 TRACE("(%p)->()\n", iface
);
1704 EnterCriticalSection(This
->crst
);
1705 setALContext(This
->ctx
);
1707 alSourcePause(This
->source
);
1709 /* Mac OS X doesn't immediately report state change
1710 * if Play() is immediately called after Stop, this can be fatal,
1711 * the buffer would never be restarted
1715 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1716 if(state
!= AL_PLAYING
)
1721 /* Stopped, remove from notify list */
1725 DWORD pos
= This
->lastpos
;
1726 hr
= IDirectSoundBuffer8_GetCurrentPosition(iface
, &pos
, NULL
);
1728 ERR("Own getcurrentposition failed!\n");
1729 trigger_notifies(This
, This
->lastpos
, pos
, TRUE
);
1730 This
->lastpos
= pos
;
1731 DS8Buffer_removenotify(This
);
1734 This
->isplaying
= FALSE
;
1737 LeaveCriticalSection(This
->crst
);
1742 static HRESULT WINAPI
DS8Buffer_Unlock(IDirectSoundBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1744 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1745 DS8Data
*buf
= This
->buffer
;
1746 DWORD bufsize
= buf
->buf_size
;
1747 DWORD_PTR ofs1
, ofs2
;
1748 DWORD_PTR boundary
= (DWORD_PTR
)buf
->data
;
1751 TRACE("(%p)->(%p, %u, %p, %u)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1753 EnterCriticalSection(This
->crst
);
1754 setALContext(This
->ctx
);
1756 This
->buffer
->locked
= 0;
1757 hr
= DSERR_INVALIDPARAM
;
1759 /* Make sure offset is between boundary and boundary + bufsize */
1760 ofs1
= (DWORD_PTR
)ptr1
;
1761 ofs2
= (DWORD_PTR
)ptr2
;
1764 if(ofs2
&& ofs2
!= boundary
)
1768 if(bufsize
-ofs1
< len1
|| len2
> ofs1
)
1777 if(This
->ExtAL
->BufferDataStatic
)
1780 if(This
->ExtAL
->BufferSubSamplesSOFT
)
1782 WAVEFORMATEX
*format
= &buf
->format
.Format
;
1784 ptr1
= (BYTE
*)ptr1
- (ofs1
%format
->nBlockAlign
);
1785 ofs1
/= format
->nBlockAlign
;
1786 len1
/= format
->nBlockAlign
;
1788 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs1
, len1
,
1789 buf
->in_chans
, buf
->in_type
, ptr1
);
1790 ptr2
= (BYTE
*)ptr2
- (ofs2
%format
->nBlockAlign
);
1791 ofs2
/= format
->nBlockAlign
;
1792 len2
/= format
->nBlockAlign
;
1794 This
->ExtAL
->BufferSubSamplesSOFT(buf
->buffers
[0], ofs2
, len2
,
1795 buf
->in_chans
, buf
->in_type
, ptr2
);
1798 else if(This
->ExtAL
->BufferSubData
)
1800 WAVEFORMATEX
*format
= &buf
->format
.Format
;
1802 len1
-= len1
%format
->nBlockAlign
;
1804 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr1
,
1806 len2
-= len2
%format
->nBlockAlign
;
1808 This
->ExtAL
->BufferSubData(buf
->buffers
[0], buf
->buf_format
, ptr2
,
1814 alBufferData(buf
->buffers
[0], buf
->buf_format
,
1815 buf
->data
, buf
->buf_size
,
1816 buf
->format
.Format
.nSamplesPerSec
);
1822 WARN("Invalid parameters (0x%lx,%u) (%p,%u,%p,%u)\n", boundary
, bufsize
, ptr1
, len1
, ptr2
, len2
);
1824 LeaveCriticalSection(This
->crst
);
1828 static HRESULT WINAPI
DS8Buffer_Restore(IDirectSoundBuffer8
*iface
)
1830 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1833 TRACE("(%p)->()\n", iface
);
1835 EnterCriticalSection(This
->crst
);
1836 if(This
->primary
->parent
->prio_level
< DSSCL_WRITEPRIMARY
||
1837 iface
== This
->primary
->write_emu
)
1839 This
->bufferlost
= 0;
1843 hr
= DSERR_BUFFERLOST
;
1844 LeaveCriticalSection(This
->crst
);
1849 static HRESULT WINAPI
DS8Buffer_SetFX(IDirectSoundBuffer8
*iface
, DWORD fxcount
, DSEFFECTDESC
*desc
, DWORD
*rescodes
)
1851 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1854 TRACE("(%p)->(%u, %p, %p)\n", This
, fxcount
, desc
, rescodes
);
1856 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFX
))
1858 WARN("FX control not set\n");
1859 return DSERR_CONTROLUNAVAIL
;
1864 if(desc
|| rescodes
)
1866 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1867 return DSERR_INVALIDPARAM
;
1870 /* No effects; we can handle that */
1874 if(!desc
|| !rescodes
)
1876 WARN("NULL desc and/or result pointer specified.\n");
1877 return DSERR_INVALIDPARAM
;
1880 /* We don't (currently) handle DSound effects */
1881 for(i
= 0;i
< fxcount
;++i
)
1883 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc
[i
].guidDSFXClass
));
1884 rescodes
[i
] = DSFXR_FAILED
;
1887 return DSERR_INVALIDPARAM
;
1890 static HRESULT WINAPI
DS8Buffer_AcquireResources(IDirectSoundBuffer8
*iface
, DWORD flags
, DWORD fxcount
, DWORD
*rescodes
)
1892 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1894 TRACE("(%p)->(%u, %u, %p)\n", This
, flags
, fxcount
, rescodes
);
1896 /* effects aren't supported at the moment.. */
1897 if(fxcount
!= 0 || rescodes
)
1899 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1900 return DSERR_INVALIDPARAM
;
1903 EnterCriticalSection(This
->crst
);
1904 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1906 This
->buffer
->dsbflags
&= ~(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
);
1907 if((flags
&DSBPLAY_LOCSOFTWARE
))
1908 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1910 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1912 LeaveCriticalSection(This
->crst
);
1917 static HRESULT WINAPI
DS8Buffer_GetObjectInPath(IDirectSoundBuffer8
*iface
, REFGUID guid
, DWORD idx
, REFGUID rguidiface
, void **ppv
)
1919 FIXME("(%p)->(%s, %u, %s, %p) : stub!\n", iface
, debugstr_guid(guid
), idx
, debugstr_guid(rguidiface
), ppv
);
1923 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
=
1925 DS8Buffer_QueryInterface
,
1929 DS8Buffer_GetCurrentPosition
,
1930 DS8Buffer_GetFormat
,
1931 DS8Buffer_GetVolume
,
1933 DS8Buffer_GetFrequency
,
1934 DS8Buffer_GetStatus
,
1935 DS8Buffer_Initialize
,
1938 DS8Buffer_SetCurrentPosition
,
1939 DS8Buffer_SetFormat
,
1940 DS8Buffer_SetVolume
,
1942 DS8Buffer_SetFrequency
,
1947 DS8Buffer_AcquireResources
,
1948 DS8Buffer_GetObjectInPath
1951 static inline DS8Buffer
*impl_from_IDirectSound3DBuffer(IDirectSound3DBuffer
*iface
)
1953 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSound3DBuffer_iface
);
1956 static HRESULT WINAPI
DS8Buffer3D_QueryInterface(IDirectSound3DBuffer
*iface
, REFIID riid
, void **ppv
)
1958 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1959 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
1962 static ULONG WINAPI
DS8Buffer3D_AddRef(IDirectSound3DBuffer
*iface
)
1964 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1967 InterlockedIncrement(&This
->all_ref
);
1968 ret
= InterlockedIncrement(&This
->ds3d_ref
);
1969 TRACE("new refcount %d\n", ret
);
1974 static ULONG WINAPI
DS8Buffer3D_Release(IDirectSound3DBuffer
*iface
)
1976 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1979 ret
= InterlockedDecrement(&This
->ds3d_ref
);
1980 TRACE("new refcount %d\n", ret
);
1981 if(InterlockedDecrement(&This
->all_ref
) == 0)
1982 DS8Buffer_Destroy(This
);
1987 static HRESULT WINAPI
DS8Buffer3D_GetAllParameters(IDirectSound3DBuffer
*iface
, DS3DBUFFER
*ds3dbuffer
)
1989 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1993 TRACE("%p\n", This
);
1995 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
1997 WARN("Invalid parameters %p %u\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
1998 return DSERR_INVALIDPARAM
;
2000 ds3dbuf
.dwSize
= sizeof(ds3dbuf
);
2002 EnterCriticalSection(This
->crst
);
2003 setALContext(This
->ctx
);
2005 hr
= IDirectSound3DBuffer_GetPosition(iface
, &ds3dbuf
.vPosition
);
2007 hr
= IDirectSound3DBuffer_GetVelocity(iface
, &ds3dbuf
.vVelocity
);
2009 hr
= IDirectSound3DBuffer_GetConeAngles(iface
, &ds3dbuf
.dwInsideConeAngle
, &ds3dbuf
.dwOutsideConeAngle
);
2011 hr
= IDirectSound3DBuffer_GetConeOrientation(iface
, &ds3dbuf
.vConeOrientation
);
2013 hr
= IDirectSound3DBuffer_GetConeOutsideVolume(iface
, &ds3dbuf
.lConeOutsideVolume
);
2015 hr
= IDirectSound3DBuffer_GetMinDistance(iface
, &ds3dbuf
.flMinDistance
);
2017 hr
= IDirectSound3DBuffer_GetMaxDistance(iface
, &ds3dbuf
.flMaxDistance
);
2019 hr
= IDirectSound3DBuffer_GetMode(iface
, &ds3dbuf
.dwMode
);
2021 memcpy(ds3dbuffer
, &ds3dbuf
, sizeof(ds3dbuf
));
2024 LeaveCriticalSection(This
->crst
);
2029 static HRESULT WINAPI
DS8Buffer3D_GetConeAngles(IDirectSound3DBuffer
*iface
, DWORD
*pdwInsideConeAngle
, DWORD
*pdwOutsideConeAngle
)
2031 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2032 ALint inangle
, outangle
;
2034 TRACE("(%p)->(%p, %p)\n", This
, pdwInsideConeAngle
, pdwOutsideConeAngle
);
2035 if(!pdwInsideConeAngle
|| !pdwOutsideConeAngle
)
2037 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle
, pdwOutsideConeAngle
);
2038 return DSERR_INVALIDPARAM
;
2041 EnterCriticalSection(This
->crst
);
2042 setALContext(This
->ctx
);
2044 alGetSourcei(This
->source
, AL_CONE_INNER_ANGLE
, &inangle
);
2045 alGetSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, &outangle
);
2047 *pdwInsideConeAngle
= inangle
;
2048 *pdwOutsideConeAngle
= outangle
;
2051 LeaveCriticalSection(This
->crst
);
2056 static HRESULT WINAPI
DS8Buffer3D_GetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVECTOR
*orient
)
2058 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2061 TRACE("(%p)->(%p)\n", This
, orient
);
2064 WARN("Invalid pointer\n");
2065 return DSERR_INVALIDPARAM
;
2068 EnterCriticalSection(This
->crst
);
2069 setALContext(This
->ctx
);
2071 alGetSourcefv(This
->source
, AL_DIRECTION
, dir
);
2075 orient
->z
= -dir
[2];
2078 LeaveCriticalSection(This
->crst
);
2083 static HRESULT WINAPI
DS8Buffer3D_GetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG
*vol
)
2085 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2088 TRACE("(%p)->(%p)\n", This
, vol
);
2091 WARN("Invalid pointer\n");
2092 return DSERR_INVALIDPARAM
;
2095 EnterCriticalSection(This
->crst
);
2096 setALContext(This
->ctx
);
2098 alGetSourcef(This
->source
, AL_CONE_OUTER_GAIN
, &gain
);
2100 *vol
= gain_to_mB(gain
);
2101 *vol
= max(*vol
, DSBVOLUME_MIN
);
2102 *vol
= min(*vol
, DSBVOLUME_MAX
);
2105 LeaveCriticalSection(This
->crst
);
2109 static HRESULT WINAPI
DS8Buffer3D_GetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*maxdist
)
2111 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2114 TRACE("(%p)->(%p)\n", This
, maxdist
);
2117 WARN("Invalid pointer\n");
2118 return DSERR_INVALIDPARAM
;
2121 EnterCriticalSection(This
->crst
);
2122 setALContext(This
->ctx
);
2124 alGetSourcef(This
->source
, AL_MAX_DISTANCE
, &dist
);
2129 LeaveCriticalSection(This
->crst
);
2134 static HRESULT WINAPI
DS8Buffer3D_GetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*mindist
)
2136 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2139 TRACE("(%p)->(%p)\n", This
, mindist
);
2142 WARN("Invalid pointer\n");
2143 return DSERR_INVALIDPARAM
;
2146 EnterCriticalSection(This
->crst
);
2147 setALContext(This
->ctx
);
2149 alGetSourcef(This
->source
, AL_REFERENCE_DISTANCE
, &dist
);
2154 LeaveCriticalSection(This
->crst
);
2159 static HRESULT WINAPI
DS8Buffer3D_GetMode(IDirectSound3DBuffer
*iface
, DWORD
*mode
)
2161 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2163 TRACE("(%p)->(%p)\n", This
, mode
);
2166 WARN("Invalid pointer\n");
2167 return DSERR_INVALIDPARAM
;
2170 EnterCriticalSection(This
->crst
);
2171 *mode
= This
->ds3dmode
;
2172 LeaveCriticalSection(This
->crst
);
2177 static HRESULT WINAPI
DS8Buffer3D_GetPosition(IDirectSound3DBuffer
*iface
, D3DVECTOR
*pos
)
2179 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2182 TRACE("(%p)->(%p)\n", This
, pos
);
2185 WARN("Invalid pointer\n");
2186 return DSERR_INVALIDPARAM
;
2189 EnterCriticalSection(This
->crst
);
2190 setALContext(This
->ctx
);
2192 alGetSourcefv(This
->source
, AL_POSITION
, alpos
);
2199 LeaveCriticalSection(This
->crst
);
2204 static HRESULT WINAPI
DS8Buffer3D_GetVelocity(IDirectSound3DBuffer
*iface
, D3DVECTOR
*vel
)
2206 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2209 TRACE("(%p)->(%p)\n", This
, vel
);
2212 WARN("Invalid pointer\n");
2213 return DSERR_INVALIDPARAM
;
2216 EnterCriticalSection(This
->crst
);
2217 setALContext(This
->ctx
);
2219 alGetSourcefv(This
->source
, AL_VELOCITY
, alvel
);
2226 LeaveCriticalSection(This
->crst
);
2231 static HRESULT WINAPI
DS8Buffer3D_SetAllParameters(IDirectSound3DBuffer
*iface
, const DS3DBUFFER
*ds3dbuffer
, DWORD apply
)
2233 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2234 TRACE("(%p)->(%p, %u)\n", This
, ds3dbuffer
, apply
);
2236 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2238 WARN("Invalid DS3DBUFFER (%p, %u)\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2239 return DSERR_INVALIDPARAM
;
2242 if(ds3dbuffer
->dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2243 ds3dbuffer
->dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2245 WARN("Invalid cone angles (%u, %u)\n", ds3dbuffer
->dwInsideConeAngle
,
2246 ds3dbuffer
->dwOutsideConeAngle
);
2247 return DSERR_INVALIDPARAM
;
2250 if(ds3dbuffer
->lConeOutsideVolume
> DSBVOLUME_MAX
||
2251 ds3dbuffer
->lConeOutsideVolume
< DSBVOLUME_MIN
)
2253 WARN("Invalid cone outside volume (%d)\n", ds3dbuffer
->lConeOutsideVolume
);
2254 return DSERR_INVALIDPARAM
;
2257 if(ds3dbuffer
->flMaxDistance
< 0.0f
)
2259 WARN("Invalid max distance (%f)\n", ds3dbuffer
->flMaxDistance
);
2260 return DSERR_INVALIDPARAM
;
2263 if(ds3dbuffer
->flMinDistance
< 0.0f
)
2265 WARN("Invalid min distance (%f)\n", ds3dbuffer
->flMinDistance
);
2266 return DSERR_INVALIDPARAM
;
2269 if(ds3dbuffer
->dwMode
!= DS3DMODE_NORMAL
&&
2270 ds3dbuffer
->dwMode
!= DS3DMODE_HEADRELATIVE
&&
2271 ds3dbuffer
->dwMode
!= DS3DMODE_DISABLE
)
2273 WARN("Invalid mode (%u)\n", ds3dbuffer
->dwMode
);
2274 return DSERR_INVALIDPARAM
;
2277 EnterCriticalSection(This
->crst
);
2278 setALContext(This
->ctx
);
2279 IDirectSound3DBuffer_SetPosition(iface
, ds3dbuffer
->vPosition
.x
, ds3dbuffer
->vPosition
.y
, ds3dbuffer
->vPosition
.z
, apply
);
2280 IDirectSound3DBuffer_SetVelocity(iface
, ds3dbuffer
->vVelocity
.x
, ds3dbuffer
->vVelocity
.y
, ds3dbuffer
->vVelocity
.z
, apply
);
2281 IDirectSound3DBuffer_SetConeAngles(iface
, ds3dbuffer
->dwInsideConeAngle
, ds3dbuffer
->dwOutsideConeAngle
, apply
);
2282 IDirectSound3DBuffer_SetConeOrientation(iface
, ds3dbuffer
->vConeOrientation
.x
, ds3dbuffer
->vConeOrientation
.y
, ds3dbuffer
->vConeOrientation
.z
, apply
);
2283 IDirectSound3DBuffer_SetConeOutsideVolume(iface
, ds3dbuffer
->lConeOutsideVolume
, apply
);
2284 IDirectSound3DBuffer_SetMinDistance(iface
, ds3dbuffer
->flMinDistance
, apply
);
2285 IDirectSound3DBuffer_SetMaxDistance(iface
, ds3dbuffer
->flMaxDistance
, apply
);
2286 IDirectSound3DBuffer_SetMode(iface
, ds3dbuffer
->dwMode
, apply
);
2288 LeaveCriticalSection(This
->crst
);
2293 static HRESULT WINAPI
DS8Buffer3D_SetConeAngles(IDirectSound3DBuffer
*iface
, DWORD dwInsideConeAngle
, DWORD dwOutsideConeAngle
, DWORD apply
)
2295 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2297 TRACE("(%p)->(%u, %u, %u)\n", This
, dwInsideConeAngle
, dwOutsideConeAngle
, apply
);
2298 if(dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2299 dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2301 WARN("Invalid cone angles (%u, %u)\n", dwInsideConeAngle
, dwOutsideConeAngle
);
2302 return DSERR_INVALIDPARAM
;
2305 EnterCriticalSection(This
->crst
);
2306 if(apply
== DS3D_DEFERRED
)
2308 This
->ds3dbuffer
.dwInsideConeAngle
= dwInsideConeAngle
;
2309 This
->ds3dbuffer
.dwOutsideConeAngle
= dwOutsideConeAngle
;
2310 This
->dirty
.bit
.cone_angles
= 1;
2314 setALContext(This
->ctx
);
2315 alSourcei(This
->source
, AL_CONE_INNER_ANGLE
, dwInsideConeAngle
);
2316 alSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, dwOutsideConeAngle
);
2320 LeaveCriticalSection(This
->crst
);
2325 static HRESULT WINAPI
DS8Buffer3D_SetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2327 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2329 TRACE("(%p)->(%f, %f, %f, %u)\n", This
, x
, y
, z
, apply
);
2331 EnterCriticalSection(This
->crst
);
2332 if(apply
== DS3D_DEFERRED
)
2334 This
->ds3dbuffer
.vConeOrientation
.x
= x
;
2335 This
->ds3dbuffer
.vConeOrientation
.y
= y
;
2336 This
->ds3dbuffer
.vConeOrientation
.z
= z
;
2337 This
->dirty
.bit
.cone_orient
= 1;
2341 setALContext(This
->ctx
);
2342 alSource3f(This
->source
, AL_DIRECTION
, x
, y
, -z
);
2346 LeaveCriticalSection(This
->crst
);
2351 static HRESULT WINAPI
DS8Buffer3D_SetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG vol
, DWORD apply
)
2353 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2355 TRACE("(%p)->(%u, %u)\n", This
, vol
, apply
);
2356 if(vol
< DSBVOLUME_MIN
|| vol
> DSBVOLUME_MAX
)
2358 WARN("Invalid volume (%u)\n", vol
);
2359 return DSERR_INVALIDPARAM
;
2362 EnterCriticalSection(This
->crst
);
2363 if(apply
== DS3D_DEFERRED
)
2365 This
->ds3dbuffer
.lConeOutsideVolume
= vol
;
2366 This
->dirty
.bit
.cone_outsidevolume
= 1;
2370 setALContext(This
->ctx
);
2371 alSourcef(This
->source
, AL_CONE_OUTER_GAIN
, mB_to_gain(vol
));
2375 LeaveCriticalSection(This
->crst
);
2380 static HRESULT WINAPI
DS8Buffer3D_SetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE maxdist
, DWORD apply
)
2382 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2384 TRACE("(%p)->(%f, %u)\n", This
, maxdist
, apply
);
2387 WARN("Invalid max distance (%f)\n", maxdist
);
2388 return DSERR_INVALIDPARAM
;
2391 EnterCriticalSection(This
->crst
);
2392 if(apply
== DS3D_DEFERRED
)
2394 This
->ds3dbuffer
.flMaxDistance
= maxdist
;
2395 This
->dirty
.bit
.max_distance
= 1;
2399 setALContext(This
->ctx
);
2400 alSourcef(This
->source
, AL_MAX_DISTANCE
, maxdist
);
2404 LeaveCriticalSection(This
->crst
);
2409 static HRESULT WINAPI
DS8Buffer3D_SetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE mindist
, DWORD apply
)
2411 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2413 TRACE("(%p)->(%f, %u)\n", This
, mindist
, apply
);
2416 WARN("Invalid min distance (%f)\n", mindist
);
2417 return DSERR_INVALIDPARAM
;
2420 EnterCriticalSection(This
->crst
);
2421 if(apply
== DS3D_DEFERRED
)
2423 This
->ds3dbuffer
.flMinDistance
= mindist
;
2424 This
->dirty
.bit
.min_distance
= 1;
2428 setALContext(This
->ctx
);
2429 alSourcef(This
->source
, AL_REFERENCE_DISTANCE
, mindist
);
2433 LeaveCriticalSection(This
->crst
);
2438 static HRESULT WINAPI
DS8Buffer3D_SetMode(IDirectSound3DBuffer
*iface
, DWORD mode
, DWORD apply
)
2440 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2442 TRACE("(%p)->(%u, %u)\n", This
, mode
, apply
);
2443 if(mode
!= DS3DMODE_NORMAL
&& mode
!= DS3DMODE_HEADRELATIVE
&&
2444 mode
!= DS3DMODE_DISABLE
)
2446 WARN("Invalid mode (%u)\n", mode
);
2447 return DSERR_INVALIDPARAM
;
2450 EnterCriticalSection(This
->crst
);
2451 if(apply
== DS3D_DEFERRED
)
2453 This
->ds3dbuffer
.dwMode
= mode
;
2454 This
->dirty
.bit
.mode
= 1;
2458 setALContext(This
->ctx
);
2459 alSourcei(This
->source
, AL_SOURCE_RELATIVE
,
2460 (mode
!= DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
2461 alSourcef(This
->source
, AL_ROLLOFF_FACTOR
,
2462 (mode
== DS3DMODE_DISABLE
) ? 0.0f
: This
->primary
->rollofffactor
);
2463 This
->ds3dmode
= mode
;
2467 LeaveCriticalSection(This
->crst
);
2472 static HRESULT WINAPI
DS8Buffer3D_SetPosition(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2474 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2476 TRACE("(%p)->(%f, %f, %f, %u)\n", This
, x
, y
, z
, apply
);
2478 EnterCriticalSection(This
->crst
);
2479 if(apply
== DS3D_DEFERRED
)
2481 This
->ds3dbuffer
.vPosition
.x
= x
;
2482 This
->ds3dbuffer
.vPosition
.y
= y
;
2483 This
->ds3dbuffer
.vPosition
.z
= z
;
2484 This
->dirty
.bit
.pos
= 1;
2488 setALContext(This
->ctx
);
2489 alSource3f(This
->source
, AL_POSITION
, x
, y
, -z
);
2493 LeaveCriticalSection(This
->crst
);
2498 static HRESULT WINAPI
DS8Buffer3D_SetVelocity(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2500 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2502 TRACE("(%p)->(%f, %f, %f, %u)\n", This
, x
, y
, z
, apply
);
2504 EnterCriticalSection(This
->crst
);
2505 if(apply
== DS3D_DEFERRED
)
2507 This
->ds3dbuffer
.vVelocity
.x
= x
;
2508 This
->ds3dbuffer
.vVelocity
.y
= y
;
2509 This
->ds3dbuffer
.vVelocity
.z
= z
;
2510 This
->dirty
.bit
.vel
= 1;
2514 setALContext(This
->ctx
);
2515 alSource3f(This
->source
, AL_VELOCITY
, x
, y
, -z
);
2519 LeaveCriticalSection(This
->crst
);
2524 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
=
2526 DS8Buffer3D_QueryInterface
,
2528 DS8Buffer3D_Release
,
2529 DS8Buffer3D_GetAllParameters
,
2530 DS8Buffer3D_GetConeAngles
,
2531 DS8Buffer3D_GetConeOrientation
,
2532 DS8Buffer3D_GetConeOutsideVolume
,
2533 DS8Buffer3D_GetMaxDistance
,
2534 DS8Buffer3D_GetMinDistance
,
2535 DS8Buffer3D_GetMode
,
2536 DS8Buffer3D_GetPosition
,
2537 DS8Buffer3D_GetVelocity
,
2538 DS8Buffer3D_SetAllParameters
,
2539 DS8Buffer3D_SetConeAngles
,
2540 DS8Buffer3D_SetConeOrientation
,
2541 DS8Buffer3D_SetConeOutsideVolume
,
2542 DS8Buffer3D_SetMaxDistance
,
2543 DS8Buffer3D_SetMinDistance
,
2544 DS8Buffer3D_SetMode
,
2545 DS8Buffer3D_SetPosition
,
2546 DS8Buffer3D_SetVelocity
2549 static inline DS8Buffer
*impl_from_IDirectSoundNotify(IDirectSoundNotify
*iface
)
2551 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundNotify_iface
);
2554 static HRESULT WINAPI
DS8BufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
2556 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2557 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2560 static ULONG WINAPI
DS8BufferNot_AddRef(IDirectSoundNotify
*iface
)
2562 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2565 InterlockedIncrement(&This
->all_ref
);
2566 ret
= InterlockedIncrement(&This
->not_ref
);
2567 TRACE("new refcount %d\n", ret
);
2572 static ULONG WINAPI
DS8BufferNot_Release(IDirectSoundNotify
*iface
)
2574 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2577 ret
= InterlockedDecrement(&This
->not_ref
);
2578 TRACE("new refcount %d\n", ret
);
2579 if(InterlockedDecrement(&This
->all_ref
) == 0)
2580 DS8Buffer_Destroy(This
);
2585 static HRESULT WINAPI
DS8BufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
2587 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2588 DSBPOSITIONNOTIFY
*nots
;
2592 EnterCriticalSection(This
->crst
);
2593 hr
= DSERR_INVALIDPARAM
;
2594 if(count
&& !notifications
)
2597 hr
= IDirectSoundBuffer8_GetStatus(&This
->IDirectSoundBuffer8_iface
, &state
);
2601 hr
= DSERR_INVALIDCALL
;
2602 if((state
&DSBSTATUS_PLAYING
))
2607 HeapFree(GetProcessHeap(), 0, This
->notify
);
2616 hr
= DSERR_INVALIDPARAM
;
2617 for(i
= 0;i
< count
;++i
)
2619 if(notifications
[i
].dwOffset
>= This
->buffer
->buf_size
&&
2620 notifications
[i
].dwOffset
!= (DWORD
)DSBPN_OFFSETSTOP
)
2625 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
2628 memcpy(nots
, notifications
, count
*sizeof(*nots
));
2630 HeapFree(GetProcessHeap(), 0, This
->notify
);
2631 This
->notify
= nots
;
2632 This
->nnotify
= count
;
2638 LeaveCriticalSection(This
->crst
);
2642 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
=
2644 DS8BufferNot_QueryInterface
,
2645 DS8BufferNot_AddRef
,
2646 DS8BufferNot_Release
,
2647 DS8BufferNot_SetNotificationPositions
2650 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2651 handled through secondary buffers. */
2652 static inline DS8Buffer
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
2654 return CONTAINING_RECORD(iface
, DS8Buffer
, IKsPropertySet_iface
);
2657 static HRESULT WINAPI
DS8BufferProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
2659 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2660 return IDirectSoundBuffer8_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2663 static ULONG WINAPI
DS8BufferProp_AddRef(IKsPropertySet
*iface
)
2665 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2668 InterlockedIncrement(&This
->all_ref
);
2669 ret
= InterlockedIncrement(&This
->prop_ref
);
2670 TRACE("new refcount %d\n", ret
);
2675 static ULONG WINAPI
DS8BufferProp_Release(IKsPropertySet
*iface
)
2677 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2680 ret
= InterlockedDecrement(&This
->prop_ref
);
2681 TRACE("new refcount %d\n", ret
);
2682 if(InterlockedDecrement(&This
->all_ref
) == 0)
2683 DS8Buffer_Destroy(This
);
2688 static HRESULT WINAPI
DS8BufferProp_Get(IKsPropertySet
*iface
,
2689 REFGUID guidPropSet
, ULONG dwPropID
,
2690 LPVOID pInstanceData
, ULONG cbInstanceData
,
2691 LPVOID pPropData
, ULONG cbPropData
,
2694 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2695 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2697 TRACE("(%p)->(%s, %u, %p, %u, %p, %u, %p)\n", iface
, debugstr_guid(guidPropSet
),
2698 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
2705 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2711 /* Not a known buffer/source property. Pass it to the listener */
2712 hr
= IKsPropertySet_Get(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2713 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
,
2720 static HRESULT WINAPI
DS8BufferProp_Set(IKsPropertySet
*iface
,
2721 REFGUID guidPropSet
, ULONG dwPropID
,
2722 LPVOID pInstanceData
, ULONG cbInstanceData
,
2723 LPVOID pPropData
, ULONG cbPropData
)
2725 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2726 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2728 TRACE("(%p)->(%s, %u, %p, %u, %p, %u)\n", iface
, debugstr_guid(guidPropSet
),
2729 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
2732 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2738 /* Not a known buffer/source property. Pass it to the listener */
2739 hr
= IKsPropertySet_Set(&This
->primary
->IKsPropertySet_iface
, guidPropSet
,
2740 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
,
2747 static HRESULT WINAPI
DS8BufferProp_QuerySupport(IKsPropertySet
*iface
,
2748 REFGUID guidPropSet
, ULONG dwPropID
,
2749 PULONG pTypeSupport
)
2751 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2752 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2754 TRACE("(%p)->(%s, %u, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
2761 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2767 /* Not a known buffer/source property. Pass it to the listener */
2768 hr
= IKsPropertySet_QuerySupport(&This
->primary
->IKsPropertySet_iface
,
2769 guidPropSet
, dwPropID
, pTypeSupport
);
2775 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
=
2777 DS8BufferProp_QueryInterface
,
2778 DS8BufferProp_AddRef
,
2779 DS8BufferProp_Release
,
2782 DS8BufferProp_QuerySupport