Avoid some casts
[dsound-openal.git] / buffer.c
blobfe63cd6b214c95b09d429694c5fd5f4f6aa95e4a
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
23 #include <stdarg.h>
25 #ifdef __WINESRC__
27 #define COBJMACROS
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "winnls.h"
34 #include "winreg.h"
35 #include "vfwmsgs.h"
36 #include "mmsystem.h"
37 #include "winternl.h"
38 #include "mmddk.h"
39 #include "wine/debug.h"
40 #include "dsound.h"
42 #include "dsound_private.h"
44 #include "ks.h"
45 #include "ksmedia.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
49 #else
51 #define WINVER 0x0600
52 #define INITGUID
53 #include <windows.h>
54 #include <dsound.h>
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)
67 #endif
69 #endif
71 #ifndef WAVE_FORMAT_IEEE_FLOAT
72 #define WAVE_FORMAT_IEEE_FLOAT 3
73 #endif
75 /* TODO: when bufferlost is set, return from all calls except initialize with
76 * DSERR_BUFFERLOST
78 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl;
79 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl;
80 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl;
81 static const IKsPropertySetVtbl DS8BufferProp_Vtbl;
84 static inline DS8Buffer *impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8 *iface)
86 return CONTAINING_RECORD(iface, DS8Buffer, IDirectSoundBuffer8_iface);
88 /* Shares the same vtable */
89 static inline DS8Buffer *impl_from_IDirectSoundBuffer(IDirectSoundBuffer *iface)
91 return CONTAINING_RECORD(iface, DS8Buffer, IDirectSoundBuffer8_iface);
94 static inline DS8Buffer *impl_from_IDirectSound3DBuffer(IDirectSound3DBuffer *iface)
96 return CONTAINING_RECORD(iface, DS8Buffer, IDirectSound3DBuffer_iface);
99 static inline DS8Buffer *impl_from_IDirectSoundNotify(IDirectSoundNotify *iface)
101 return CONTAINING_RECORD(iface, DS8Buffer, IDirectSoundNotify_iface);
104 static inline DS8Buffer *impl_from_IKsPropertySet(IKsPropertySet *iface)
106 return CONTAINING_RECORD(iface, DS8Buffer, IKsPropertySet_iface);
110 static void CALLBACK DS8Buffer_timer(UINT timerID, UINT msg, DWORD_PTR dwUser,
111 DWORD_PTR dw1, DWORD_PTR dw2)
113 (void)timerID;
114 (void)msg;
115 (void)dw1;
116 (void)dw2;
117 PostThreadMessageA(dwUser, WM_USER, 0, 0);
120 static void DS8Buffer_starttimer(DS8Primary *prim)
122 DWORD triggertime, res = DS_TIME_RES;
123 ALint refresh = FAKE_REFRESH_COUNT;
124 TIMECAPS time;
126 if(prim->timer_id)
127 return;
129 timeGetDevCaps(&time, sizeof(TIMECAPS));
131 alcGetIntegerv(prim->parent->device, ALC_REFRESH, 1, &refresh);
132 getALCError(prim->parent->device);
134 triggertime = 1000 / refresh / 2;
135 if(triggertime < time.wPeriodMin)
136 triggertime = time.wPeriodMin;
137 TRACE("Calling timer every %u ms for %i refreshes per second\n", triggertime, refresh);
139 if (res < time.wPeriodMin)
140 res = time.wPeriodMin;
141 if (timeBeginPeriod(res) == TIMERR_NOCANDO)
142 WARN("Could not set minimum resolution, don't expect sound\n");
144 prim->timer_res = res;
145 prim->timer_id = timeSetEvent(triggertime, res, DS8Buffer_timer, prim->thread_id, TIME_PERIODIC|TIME_KILL_SYNCHRONOUS);
148 /* Should be called with critsect held and context set.. */
149 static void DS8Buffer_addnotify(DS8Buffer *buf)
151 DS8Buffer **list;
152 DWORD i;
154 list = buf->primary->notifies;
155 for(i = 0; i < buf->primary->nnotifies; ++i)
157 if(buf == list[i])
159 ERR("Buffer %p already in notification list\n", buf);
160 return;
163 if(buf->primary->nnotifies == buf->primary->sizenotifies)
165 list = HeapReAlloc(GetProcessHeap(), 0, list, (buf->primary->nnotifies + 1) * sizeof(*list));
166 if(!list)
167 return;
168 buf->primary->sizenotifies++;
170 list[buf->primary->nnotifies++] = buf;
171 buf->primary->notifies = list;
175 static const char *get_fmtstr_PCM(const DS8Primary *prim, const WAVEFORMATEX *format, WAVEFORMATEXTENSIBLE *out, ALenum *in_chans, ALenum *in_type)
177 out->Format = *format;
178 out->Format.cbSize = 0;
180 if(format->wBitsPerSample == 8)
182 *in_type = AL_UNSIGNED_BYTE;
183 switch(format->nChannels)
185 case 1: *in_chans = AL_MONO;
186 return "AL_FORMAT_MONO8";
187 case 2: *in_chans = AL_STEREO;
188 return "AL_FORMAT_STEREO8";
189 case 4: *in_chans = AL_QUAD;
190 return "AL_FORMAT_QUAD8";
191 case 6: *in_chans = AL_5POINT1;
192 return "AL_FORMAT_51CHN8";
193 case 7: *in_chans = AL_6POINT1;
194 return "AL_FORMAT_61CHN8";
195 case 8: *in_chans = AL_7POINT1;
196 return "AL_FORMAT_71CHN8";
197 default: break;
200 else if(format->wBitsPerSample == 16)
202 *in_type = AL_SHORT;
203 switch(format->nChannels)
205 case 1: *in_chans = AL_MONO;
206 return "AL_FORMAT_MONO16";
207 case 2: *in_chans = AL_STEREO;
208 return "AL_FORMAT_STEREO16";
209 case 4: *in_chans = AL_QUAD;
210 return "AL_FORMAT_QUAD16";
211 case 6: *in_chans = AL_5POINT1;
212 return "AL_FORMAT_51CHN16";
213 case 7: *in_chans = AL_6POINT1;
214 return "AL_FORMAT_61CHN16";
215 case 8: *in_chans = AL_7POINT1;
216 return "AL_FORMAT_71CHN16";
217 default: break;
220 #if 0 /* Will cause incorrect byte offsets */
221 else if(format->wBitsPerSample == 24 && prim->SupportedExt[SOFT_BUFFER_SAMPLES])
223 *in_type = AL_BYTE3;
224 switch(format->nChannels)
226 case 1: *in_chans = AL_MONO;
227 return "AL_MONO32F";
228 case 2: *in_chans = AL_STEREO;
229 return "AL_STEREO32F";
230 case 4: *in_chans = AL_QUAD;
231 return "AL_QUAD32F";
232 case 6: *in_chans = AL_5POINT1;
233 return "AL_5POINT1_32F";
234 case 7: *in_chans = AL_6POINT1;
235 return "AL_6POINT1_32F";
236 case 8: *in_chans = AL_7POINT1;
237 return "AL_7POINT1_32F";
238 default: break;
241 #endif
242 else if(format->wBitsPerSample == 32 && prim->SupportedExt[SOFT_BUFFER_SAMPLES])
244 *in_type = AL_INT;
245 switch(format->nChannels)
247 case 1: *in_chans = AL_MONO;
248 return "AL_MONO32F";
249 case 2: *in_chans = AL_STEREO;
250 return "AL_STEREO32F";
251 case 4: *in_chans = AL_QUAD;
252 return "AL_QUAD32F";
253 case 6: *in_chans = AL_5POINT1;
254 return "AL_5POINT1_32F";
255 case 7: *in_chans = AL_6POINT1;
256 return "AL_6POINT1_32F";
257 case 8: *in_chans = AL_7POINT1;
258 return "AL_7POINT1_32F";
259 default: break;
263 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
264 format->wBitsPerSample, format->nChannels);
265 return NULL;
268 static const char *get_fmtstr_FLOAT(const DS8Primary *prim, const WAVEFORMATEX *format, WAVEFORMATEXTENSIBLE *out, ALenum *in_chans, ALenum *in_type)
270 out->Format = *format;
271 out->Format.cbSize = 0;
273 if(format->wBitsPerSample == 32 &&
274 (prim->SupportedExt[EXT_FLOAT32] || prim->SupportedExt[SOFT_BUFFER_SAMPLES]))
276 *in_type = AL_FLOAT;
277 switch(format->nChannels)
279 case 1: *in_chans = AL_MONO;
280 return "AL_FORMAT_MONO_FLOAT32";
281 case 2: *in_chans = AL_STEREO;
282 return "AL_FORMAT_STEREO_FLOAT32";
283 case 4: *in_chans = AL_QUAD;
284 return "AL_FORMAT_QUAD32";
285 case 6: *in_chans = AL_5POINT1;
286 return "AL_FORMAT_51CHN32";
287 case 7: *in_chans = AL_6POINT1;
288 return "AL_FORMAT_61CHN32";
289 case 8: *in_chans = AL_7POINT1;
290 return "AL_FORMAT_71CHN32";
291 default: break;
294 #if 0 /* Will cause incorrect byte offsets */
295 else if(format->wBitsPerSample == 64 && prim->SupportedExt[SOFT_BUFFER_SAMPLES])
297 *in_type = AL_DOUBLE;
298 switch(format->nChannels)
300 case 1: *in_chans = AL_MONO;
301 return "AL_MONO32F";
302 case 2: *in_chans = AL_STEREO;
303 return "AL_STEREO32F";
304 case 4: *in_chans = AL_QUAD;
305 return "AL_QUAD32F";
306 case 6: *in_chans = AL_5POINT1;
307 return "AL_5POINT1_32F";
308 case 7: *in_chans = AL_6POINT1;
309 return "AL_6POINT1_32F";
310 case 8: *in_chans = AL_7POINT1;
311 return "AL_7POINT1_32F";
312 default: break;
315 #endif
317 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
318 format->wBitsPerSample, format->nChannels);
319 return NULL;
322 /* Speaker configs */
323 #define MONO SPEAKER_FRONT_CENTER
324 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
325 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
326 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
327 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
328 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
329 #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)
331 static const char *get_fmtstr_EXT(const DS8Primary *prim, const WAVEFORMATEX *format, WAVEFORMATEXTENSIBLE *out, ALenum *in_chans, ALenum *in_type)
333 *out = *(const WAVEFORMATEXTENSIBLE*)format;
334 out->Format.cbSize = sizeof(*out) - sizeof(out->Format);
336 if(!out->Samples.wValidBitsPerSample)
337 out->Samples.wValidBitsPerSample = out->Format.wBitsPerSample;
338 else if(out->Samples.wValidBitsPerSample != out->Format.wBitsPerSample)
340 FIXME("Padded samples not supported (%u of %u)\n", out->Samples.wValidBitsPerSample, out->Format.wBitsPerSample);
341 return NULL;
344 if(out->dwChannelMask != MONO && out->dwChannelMask != STEREO &&
345 !prim->SupportedExt[EXT_MCFORMATS] && !prim->SupportedExt[SOFT_BUFFER_SAMPLES])
347 WARN("Multi-channel not available\n");
348 return NULL;
351 if(IsEqualGUID(&out->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))
353 if(out->Samples.wValidBitsPerSample == 8)
355 *in_type = AL_UNSIGNED_BYTE;
356 switch(out->dwChannelMask)
358 case MONO: *in_chans = AL_MONO;
359 return "AL_FORMAT_MONO8";
360 case STEREO: *in_chans = AL_STEREO;
361 return "AL_FORMAT_STEREO8";
362 case REAR: *in_chans = AL_REAR;
363 return "AL_FORMAT_REAR8";
364 case QUAD: *in_chans = AL_QUAD;
365 return "AL_FORMAT_QUAD8";
366 case X5DOT1: *in_chans = AL_5POINT1;
367 return "AL_FORMAT_51CHN8";
368 case X6DOT1: *in_chans = AL_6POINT1;
369 return "AL_FORMAT_61CHN8";
370 case X7DOT1: *in_chans = AL_7POINT1;
371 return "AL_FORMAT_71CHN8";
372 default: break;
375 else if(out->Samples.wValidBitsPerSample == 16)
377 *in_type = AL_SHORT;
378 switch(out->dwChannelMask)
380 case MONO: *in_chans = AL_MONO;
381 return "AL_FORMAT_MONO16";
382 case STEREO: *in_chans = AL_STEREO;
383 return "AL_FORMAT_STEREO16";
384 case REAR: *in_chans = AL_REAR;
385 return "AL_FORMAT_REAR16";
386 case QUAD: *in_chans = AL_QUAD;
387 return "AL_FORMAT_QUAD16";
388 case X5DOT1: *in_chans = AL_5POINT1;
389 return "AL_FORMAT_51CHN16";
390 case X6DOT1: *in_chans = AL_6POINT1;
391 return "AL_FORMAT_61CHN16";
392 case X7DOT1: *in_chans = AL_7POINT1;
393 return "AL_FORMAT_71CHN16";
394 default: break;
397 #if 0
398 else if(out->Samples.wValidBitsPerSample == 24 &&
399 prim->SupportedExt[SOFT_BUFFER_SAMPLES])
401 *in_type = AL_BYTE3;
402 switch(out->dwChannelMask)
404 case MONO: *in_chans = AL_MONO;
405 return "AL_MONO32F";
406 case STEREO: *in_chans = AL_STEREO;
407 return "AL_STEREO32F";
408 case REAR: *in_chans = AL_REAR;
409 return "AL_REAR32F";
410 case QUAD: *in_chans = AL_QUAD;
411 return "AL_QUAD32F";
412 case X5DOT1: *in_chans = AL_5POINT1;
413 return "AL_5POINT1_32F";
414 case X6DOT1: *in_chans = AL_6POINT1;
415 return "AL_6POINT1_32F";
416 case X7DOT1: *in_chans = AL_7POINT1;
417 return "AL_7POINT1_32F";
418 default: break;
421 #endif
422 else if(out->Samples.wValidBitsPerSample == 32 &&
423 prim->SupportedExt[SOFT_BUFFER_SAMPLES])
425 *in_type = AL_INT;
426 switch(out->dwChannelMask)
428 case MONO: *in_chans = AL_MONO;
429 return "AL_MONO32F";
430 case STEREO: *in_chans = AL_STEREO;
431 return "AL_STEREO32F";
432 case REAR: *in_chans = AL_REAR;
433 return "AL_REAR32F";
434 case QUAD: *in_chans = AL_QUAD;
435 return "AL_QUAD32F";
436 case X5DOT1: *in_chans = AL_5POINT1;
437 return "AL_5POINT1_32F";
438 case X6DOT1: *in_chans = AL_6POINT1;
439 return "AL_6POINT1_32F";
440 case X7DOT1: *in_chans = AL_7POINT1;
441 return "AL_7POINT1_32F";
442 default: break;
446 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#x)\n",
447 out->Samples.wValidBitsPerSample, out->dwChannelMask);
448 return NULL;
450 else if(IsEqualGUID(&out->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) &&
451 (prim->SupportedExt[EXT_FLOAT32] || prim->SupportedExt[SOFT_BUFFER_SAMPLES]))
453 if(out->Samples.wValidBitsPerSample == 32)
455 *in_type = AL_FLOAT;
456 switch(out->dwChannelMask)
458 case MONO: *in_chans = AL_MONO;
459 return "AL_FORMAT_MONO_FLOAT32";
460 case STEREO: *in_chans = AL_STEREO;
461 return "AL_FORMAT_STEREO_FLOAT32";
462 case REAR: *in_chans = AL_REAR;
463 return "AL_FORMAT_REAR32";
464 case QUAD: *in_chans = AL_QUAD;
465 return "AL_FORMAT_QUAD32";
466 case X5DOT1: *in_chans = AL_5POINT1;
467 return "AL_FORMAT_51CHN32";
468 case X6DOT1: *in_chans = AL_6POINT1;
469 return "AL_FORMAT_61CHN32";
470 case X7DOT1: *in_chans = AL_7POINT1;
471 return "AL_FORMAT_71CHN32";
472 default: break;
475 #if 0
476 else if(out->Samples.wValidBitsPerSample == 64 &&
477 prim->SupportedExt[SOFT_BUFFER_SAMPLES])
479 *in_type = AL_DOUBLE;
480 switch(out->dwChannelMask)
482 case MONO: *in_chans = AL_MONO;
483 return "AL_MONO32F";
484 case STEREO: *in_chans = AL_STEREO;
485 return "AL_STEREO32F";
486 case REAR: *in_chans = AL_REAR;
487 return "AL_REAR32F";
488 case QUAD: *in_chans = AL_QUAD;
489 return "AL_QUAD32F";
490 case X5DOT1: *in_chans = AL_5POINT1;
491 return "AL_5POINT1_32F";
492 case X6DOT1: *in_chans = AL_6POINT1;
493 return "AL_6POINT1_32F";
494 case X7DOT1: *in_chans = AL_7POINT1;
495 return "AL_7POINT1_32F";
496 default: break;
499 #endif
500 else
502 WARN("Invalid float bits: %u\n", out->Samples.wValidBitsPerSample);
503 return NULL;
506 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#x)\n",
507 out->Samples.wValidBitsPerSample, out->dwChannelMask);
508 return NULL;
510 else if(!IsEqualGUID(&out->SubFormat, &GUID_NULL))
511 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out->SubFormat));
512 return NULL;
515 static void DS8Data_Release(DS8Data *This);
516 static HRESULT DS8Data_Create(DS8Data **ppv, const DSBUFFERDESC *desc, DS8Primary *prim)
518 HRESULT hr = DSERR_INVALIDPARAM;
519 const WAVEFORMATEX *format;
520 const char *fmt_str = NULL;
521 DS8Data *pBuffer;
523 format = desc->lpwfxFormat;
524 TRACE("Requested buffer format:\n"
525 " FormatTag = 0x%04x\n"
526 " Channels = %d\n"
527 " SamplesPerSec = %u\n"
528 " AvgBytesPerSec = %u\n"
529 " BlockAlign = %d\n"
530 " BitsPerSample = %d\n",
531 format->wFormatTag, format->nChannels,
532 format->nSamplesPerSec, format->nAvgBytesPerSec,
533 format->nBlockAlign, format->wBitsPerSample);
535 if(format->nBlockAlign == 0)
537 WARN("Invalid BlockAlign specified\n");
538 return DSERR_INVALIDPARAM;
541 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
542 * will need the EAX-RAM extension. Currently, we just tell the app it
543 * gets what it wanted. */
544 pBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pBuffer));
545 if(!pBuffer)
546 return E_OUTOFMEMORY;
547 pBuffer->ref = 1;
549 pBuffer->dsbflags = desc->dwFlags;
550 if((pBuffer->dsbflags&(DSBCAPS_LOCSOFTWARE|DSBCAPS_LOCHARDWARE)) == (DSBCAPS_LOCSOFTWARE|DSBCAPS_LOCHARDWARE))
552 WARN("Hardware and software location requested\n");
553 goto fail;
555 if(!(pBuffer->dsbflags&(DSBCAPS_LOCSOFTWARE|DSBCAPS_LOCHARDWARE|DSBCAPS_LOCDEFER)))
556 pBuffer->dsbflags |= DSBCAPS_LOCHARDWARE;
558 pBuffer->buf_size = desc->dwBufferBytes + format->nBlockAlign - 1;
559 pBuffer->buf_size -= pBuffer->buf_size%format->nBlockAlign;
561 hr = DSERR_BUFFERTOOSMALL;
562 if(pBuffer->buf_size < DSBSIZE_MIN)
563 goto fail;
565 hr = DSERR_INVALIDPARAM;
566 if(pBuffer->buf_size > DSBSIZE_MAX)
567 goto fail;
569 pBuffer->numsegs = 1;
570 pBuffer->segsize = pBuffer->buf_size;
571 pBuffer->lastsegsize = pBuffer->buf_size;
573 if(!(pBuffer->dsbflags&DSBCAPS_STATIC) && !prim->ExtAL.BufferSubData &&
574 !prim->ExtAL.BufferSamplesSOFT && !prim->ExtAL.BufferDataStatic)
576 ALCint refresh = FAKE_REFRESH_COUNT;
577 ALuint newSize;
579 alcGetIntegerv(prim->parent->device, ALC_REFRESH, 1, &refresh);
580 getALCError(prim->parent->device);
582 newSize = format->nAvgBytesPerSec/refresh + format->nBlockAlign - 1;
583 newSize -= newSize%format->nBlockAlign;
585 /* Make sure enough buffers are available */
586 if(newSize > pBuffer->buf_size/(QBUFFERS+2))
587 ERR("Buffer segments too large to stream (%u for %u)!\n",
588 newSize, pBuffer->buf_size);
589 else
591 pBuffer->numsegs = pBuffer->buf_size/newSize;
592 pBuffer->segsize = newSize;
593 pBuffer->lastsegsize = pBuffer->buf_size - (newSize*(pBuffer->numsegs-1));
594 TRACE("New streaming buffer (%u chunks, %u : %u sizes)\n",
595 pBuffer->numsegs, pBuffer->segsize, pBuffer->lastsegsize);
599 if(format->wFormatTag == WAVE_FORMAT_PCM)
600 fmt_str = get_fmtstr_PCM(prim, format, &pBuffer->format, &pBuffer->in_chans, &pBuffer->in_type);
601 else if(format->wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
602 fmt_str = get_fmtstr_FLOAT(prim, format, &pBuffer->format, &pBuffer->in_chans, &pBuffer->in_type);
603 else if(format->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
605 const WAVEFORMATEXTENSIBLE *wfe;
607 hr = DSERR_CONTROLUNAVAIL;
608 if(format->cbSize != sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX) &&
609 format->cbSize != sizeof(WAVEFORMATEXTENSIBLE))
610 goto fail;
612 wfe = (const WAVEFORMATEXTENSIBLE*)format;
613 TRACE("Extensible values:\n"
614 " Samples = %d\n"
615 " ChannelMask = %#x\n"
616 " SubFormat = %s\n",
617 wfe->Samples.wReserved, wfe->dwChannelMask,
618 debugstr_guid(&wfe->SubFormat));
620 hr = DSERR_INVALIDCALL;
621 fmt_str = get_fmtstr_EXT(prim, format, &pBuffer->format, &pBuffer->in_chans, &pBuffer->in_type);
623 else
624 ERR("Unhandled formattag 0x%04x\n", format->wFormatTag);
626 if(!fmt_str)
627 goto fail;
629 pBuffer->buf_format = alGetEnumValue(fmt_str);
630 if(alGetError() != AL_NO_ERROR || pBuffer->buf_format == 0 ||
631 pBuffer->buf_format == -1)
633 WARN("Could not get OpenAL format from %s\n", fmt_str);
634 goto fail;
637 hr = E_OUTOFMEMORY;
638 pBuffer->buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pBuffer->buffers)*pBuffer->numsegs);
639 pBuffer->data = HeapAlloc(GetProcessHeap(), 0, pBuffer->buf_size);
640 if(!pBuffer->buffers || !pBuffer->data)
641 goto fail;
643 alGenBuffers(pBuffer->numsegs, pBuffer->buffers);
644 getALError();
646 *ppv = pBuffer;
647 return S_OK;
649 fail:
650 DS8Data_Release(pBuffer);
651 return hr;
654 static void DS8Data_AddRef(DS8Data *data)
656 InterlockedIncrement(&data->ref);
659 /* This function is always called with the device lock held */
660 static void DS8Data_Release(DS8Data *This)
662 if(InterlockedDecrement(&This->ref)) return;
664 TRACE("Deleting %p\n", This);
665 if (This->buffers && This->buffers[0])
667 alDeleteBuffers(This->numsegs, This->buffers);
668 getALError();
670 HeapFree(GetProcessHeap(), 0, This->buffers);
671 HeapFree(GetProcessHeap(), 0, This->data);
672 HeapFree(GetProcessHeap(), 0, This);
675 HRESULT DS8Buffer_Create(DS8Buffer **ppv, DS8Primary *parent, IDirectSoundBuffer *orig)
677 HRESULT hr = DSERR_OUTOFMEMORY;
678 DS8Buffer *This;
679 DS8Buffer **bufs;
681 *ppv = NULL;
682 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
683 if(!This) return hr;
685 This->IDirectSoundBuffer8_iface.lpVtbl = (IDirectSoundBuffer8Vtbl*)&DS8Buffer_Vtbl;
686 This->IDirectSound3DBuffer_iface.lpVtbl = (IDirectSound3DBufferVtbl*)&DS8Buffer3d_Vtbl;
687 This->IDirectSoundNotify_iface.lpVtbl = (IDirectSoundNotifyVtbl*)&DS8BufferNot_Vtbl;
688 This->IKsPropertySet_iface.lpVtbl = (IKsPropertySetVtbl*)&DS8BufferProp_Vtbl;
690 This->primary = parent;
691 This->ctx = parent->ctx;
692 This->ExtAL = &parent->ExtAL;
693 This->crst = &parent->crst;
694 This->ref = This->all_ref = 1;
696 if(orig)
698 DS8Buffer *org = impl_from_IDirectSoundBuffer(orig);
699 DS8Data_AddRef(org->buffer);
700 This->buffer = org->buffer;
703 /* Append to buffer list */
704 bufs = parent->buffers;
705 if(parent->nbuffers == parent->sizebuffers)
707 bufs = HeapReAlloc(GetProcessHeap(), 0, bufs, sizeof(*bufs)*(1+parent->nbuffers));
708 if(!bufs) goto fail;
709 parent->sizebuffers++;
711 parent->buffers = bufs;
712 bufs[parent->nbuffers++] = This;
714 /* Disable until initialized.. */
715 This->ds3dmode = DS3DMODE_DISABLE;
717 *ppv = This;
718 return S_OK;
720 fail:
721 DS8Buffer_Destroy(This);
722 return hr;
725 void DS8Buffer_Destroy(DS8Buffer *This)
727 DS8Primary *prim = This->primary;
728 DWORD idx;
730 TRACE("Destroying %p\n", This);
732 EnterCriticalSection(&prim->crst);
733 /* Remove from list, if in list */
734 for(idx = 0;idx < prim->nnotifies;++idx)
736 if(This == prim->notifies[idx])
738 prim->notifies[idx] = prim->notifies[--prim->nnotifies];
739 break;
742 for(idx = 0;idx < prim->nbuffers;++idx)
744 if(prim->buffers[idx] == This)
746 prim->buffers[idx] = prim->buffers[--prim->nbuffers];
747 break;
751 setALContext(This->ctx);
752 if(This->source)
754 ALuint *sources;
756 alSourceStop(This->source);
757 alSourcei(This->source, AL_BUFFER, 0);
758 getALError();
760 sources = prim->sources;
761 if(prim->nsources == prim->sizesources)
763 sources = HeapReAlloc(GetProcessHeap(), 0, sources, sizeof(*sources)*(prim->nsources+1));
764 if(!sources)
765 alDeleteSources(1, &This->source);
766 else
767 prim->sizesources++;
769 if(sources)
771 sources[prim->nsources++] = This->source;
772 prim->sources = sources;
774 This->source = 0;
776 LeaveCriticalSection(&prim->crst);
778 if(This->buffer)
779 DS8Data_Release(This->buffer);
781 popALContext();
783 HeapFree(GetProcessHeap(), 0, This->notify);
784 HeapFree(GetProcessHeap(), 0, This);
788 static HRESULT WINAPI DS8Buffer_QueryInterface(IDirectSoundBuffer8 *iface, REFIID riid, void **ppv)
790 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
792 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
794 *ppv = NULL;
795 if(IsEqualIID(riid, &IID_IUnknown) ||
796 IsEqualIID(riid, &IID_IDirectSoundBuffer))
797 *ppv = &This->IDirectSoundBuffer8_iface;
798 else if(IsEqualIID(riid, &IID_IDirectSoundBuffer8))
800 if(This->primary->parent->is_8)
801 *ppv = &This->IDirectSoundBuffer8_iface;
803 else if(IsEqualIID(riid, &IID_IDirectSound3DBuffer))
805 if((This->buffer->dsbflags&DSBCAPS_CTRL3D))
806 *ppv = &This->IDirectSound3DBuffer_iface;
808 else if(IsEqualIID(riid, &IID_IDirectSoundNotify))
810 if((This->buffer->dsbflags&DSBCAPS_CTRLPOSITIONNOTIFY))
811 *ppv = &This->IDirectSoundNotify_iface;
813 else if(IsEqualIID(riid, &IID_IKsPropertySet))
814 *ppv = &This->IKsPropertySet_iface;
815 else
816 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid));
818 if(*ppv)
820 IUnknown_AddRef((IUnknown*)*ppv);
821 return S_OK;
824 return E_NOINTERFACE;
827 static ULONG WINAPI DS8Buffer_AddRef(IDirectSoundBuffer8 *iface)
829 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
830 LONG ret;
832 InterlockedIncrement(&This->all_ref);
833 ret = InterlockedIncrement(&This->ref);
834 TRACE("new refcount %d\n", ret);
836 return ret;
839 static ULONG WINAPI DS8Buffer_Release(IDirectSoundBuffer8 *iface)
841 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
842 LONG ret;
844 ret = InterlockedDecrement(&This->ref);
845 TRACE("new refcount %d\n", ret);
846 if(InterlockedDecrement(&This->all_ref) == 0)
847 DS8Buffer_Destroy(This);
849 return ret;
852 static HRESULT WINAPI DS8Buffer_GetCaps(IDirectSoundBuffer8 *iface, DSBCAPS *caps)
854 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
856 TRACE("(%p)->(%p)\n", iface, caps);
858 if(!caps || caps->dwSize < sizeof(*caps))
860 WARN("Invalid DSBCAPS (%p, %u)\n", caps, (caps ? caps->dwSize : 0));
861 return DSERR_INVALIDPARAM;
864 caps->dwFlags = This->buffer->dsbflags;
865 caps->dwBufferBytes = This->buffer->buf_size;
866 caps->dwUnlockTransferRate = 4096;
867 caps->dwPlayCpuOverhead = 0;
868 return S_OK;
871 static HRESULT WINAPI DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8 *iface, DWORD *playpos, DWORD *curpos)
873 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
874 WAVEFORMATEX *format = &This->buffer->format.Format;
875 UINT writecursor, pos;
877 TRACE("(%p)->(%p, %p)\n", iface, playpos, curpos);
879 EnterCriticalSection(This->crst);
880 setALContext(This->ctx);
882 if(This->buffer->numsegs > 1)
884 ALint queued = QBUFFERS;
885 alGetSourcei(This->source, AL_BUFFERS_QUEUED, &queued);
886 getALError();
888 pos = (This->curidx+This->buffer->numsegs-queued)%This->buffer->numsegs;
889 pos *= This->buffer->segsize;
890 writecursor = This->curidx * This->buffer->segsize;
892 else if(This->ExtAL->BufferSubData || This->ExtAL->BufferSamplesSOFT)
894 ALint rwpos[2] = { 0, 0 };
896 alGetSourceiv(This->source, AL_BYTE_RW_OFFSETS_SOFT, rwpos);
897 getALError();
899 pos = rwpos[0];
900 writecursor = rwpos[1];
902 else
904 ALint status = 0;
905 ALint ofs = 0;
907 alGetSourcei(This->source, AL_BYTE_OFFSET, &ofs);
908 alGetSourcei(This->source, AL_SOURCE_STATE, &status);
909 getALError();
911 pos = ofs;
912 if(status == AL_PLAYING)
914 writecursor = format->nSamplesPerSec / 100;
915 writecursor *= format->nBlockAlign;
917 else
918 writecursor = 0;
919 writecursor = (writecursor + pos) % This->buffer->buf_size;
921 TRACE("%p Play pos = %u, write pos = %u\n", This, pos, writecursor);
922 if(pos >= This->buffer->buf_size)
924 ERR("playpos >= buf_size\n");
925 pos %= This->buffer->buf_size;
927 if(writecursor >= This->buffer->buf_size)
929 ERR("writepos >= buf_size\n");
930 writecursor %= This->buffer->buf_size;
933 if(playpos) *playpos = pos;
934 if(curpos) *curpos = writecursor;
936 popALContext();
937 LeaveCriticalSection(This->crst);
939 return S_OK;
942 static HRESULT WINAPI DS8Buffer_GetFormat(IDirectSoundBuffer8 *iface, WAVEFORMATEX *wfx, DWORD allocated, DWORD *written)
944 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
945 HRESULT hr = S_OK;
946 UINT size;
948 TRACE("(%p)->(%p, %u, %p)\n", iface, wfx, allocated, written);
950 if(!wfx && !written)
952 WARN("Cannot report format or format size\n");
953 return DSERR_INVALIDPARAM;
956 EnterCriticalSection(This->crst);
957 size = sizeof(This->buffer->format.Format) + This->buffer->format.Format.cbSize;
958 if(wfx)
960 if(allocated < size)
961 hr = DSERR_INVALIDPARAM;
962 else
963 memcpy(wfx, &This->buffer->format.Format, size);
965 if(written)
966 *written = size;
967 LeaveCriticalSection(This->crst);
969 return hr;
972 static HRESULT WINAPI DS8Buffer_GetVolume(IDirectSoundBuffer8 *iface, LONG *vol)
974 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
975 HRESULT hr;
977 TRACE("(%p)->(%p)\n", iface, vol);
979 if(!vol)
981 WARN("Invalid pointer\n");
982 return DSERR_INVALIDPARAM;
985 EnterCriticalSection(This->crst);
987 hr = DSERR_CONTROLUNAVAIL;
988 if(!(This->buffer->dsbflags&DSBCAPS_CTRLVOLUME))
989 WARN("Volume control not set\n");
990 else
992 ALfloat gain = 1.0f;
994 setALContext(This->ctx);
995 alGetSourcef(This->source, AL_GAIN, &gain);
996 getALError();
997 popALContext();
999 *vol = gain_to_mB(gain);
1000 *vol = min(*vol, DSBVOLUME_MAX);
1001 *vol = max(*vol, DSBVOLUME_MIN);
1003 hr = DS_OK;
1006 LeaveCriticalSection(This->crst);
1007 return hr;
1010 static HRESULT WINAPI DS8Buffer_GetPan(IDirectSoundBuffer8 *iface, LONG *pan)
1012 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1013 HRESULT hr;
1015 TRACE("(%p)->(%p)\n", iface, pan);
1017 if(!pan)
1019 WARN("Invalid pointer\n");
1020 return DSERR_INVALIDPARAM;
1023 EnterCriticalSection(This->crst);
1025 hr = DSERR_CONTROLUNAVAIL;
1026 if(!(This->buffer->dsbflags&DSBCAPS_CTRLPAN))
1027 WARN("Panning control not set\n");
1028 else
1030 ALfloat pos[3];
1032 setALContext(This->ctx);
1033 alGetSourcefv(This->source, AL_POSITION, pos);
1034 getALError();
1035 popALContext();
1037 *pan = (LONG)((pos[0]+1.0) * (DSBPAN_RIGHT-DSBPAN_LEFT) / 2.0 + 0.5) + DSBPAN_LEFT;
1038 *pan = min(*pan, DSBPAN_RIGHT);
1039 *pan = max(*pan, DSBPAN_LEFT);
1041 hr = DS_OK;
1044 LeaveCriticalSection(This->crst);
1045 return hr;
1048 static HRESULT WINAPI DS8Buffer_GetFrequency(IDirectSoundBuffer8 *iface, DWORD *freq)
1050 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1051 HRESULT hr;
1053 TRACE("(%p)->(%p)\n", iface, freq);
1055 if(!freq)
1057 WARN("Invalid pointer\n");
1058 return DSERR_INVALIDPARAM;
1061 EnterCriticalSection(This->crst);
1063 hr = DSERR_CONTROLUNAVAIL;
1064 if(!(This->buffer->dsbflags&DSBCAPS_CTRLFREQUENCY))
1065 WARN("Frequency control not set\n");
1066 else
1068 ALfloat pitch = 1.0f;
1070 setALContext(This->ctx);
1071 alGetSourcefv(This->source, AL_PITCH, &pitch);
1072 getALError();
1073 popALContext();
1075 *freq = (DWORD)(This->buffer->format.Format.nSamplesPerSec * pitch);
1077 hr = DS_OK;
1080 LeaveCriticalSection(This->crst);
1081 return hr;
1084 static HRESULT WINAPI DS8Buffer_GetStatus(IDirectSoundBuffer8 *iface, DWORD *status)
1086 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1087 ALint state, looping;
1089 TRACE("(%p)->(%p)\n", iface, status);
1091 if(!status)
1093 WARN("Invalid pointer\n");
1094 return DSERR_INVALIDPARAM;
1097 EnterCriticalSection(This->crst);
1099 setALContext(This->ctx);
1100 alGetSourcei(This->source, AL_SOURCE_STATE, &state);
1101 looping = This->islooping;
1102 if(This->buffer->numsegs == 1)
1103 alGetSourcei(This->source, AL_LOOPING, &looping);
1104 else if(state != AL_PLAYING)
1105 state = This->isplaying ? AL_PLAYING : AL_PAUSED;
1106 getALError();
1107 popALContext();
1109 *status = 0;
1110 if((This->buffer->dsbflags&DSBCAPS_LOCDEFER))
1112 if((This->buffer->dsbflags&DSBCAPS_LOCSOFTWARE))
1113 *status |= DSBSTATUS_LOCSOFTWARE;
1114 else if((This->buffer->dsbflags&DSBCAPS_LOCHARDWARE))
1115 *status |= DSBSTATUS_LOCHARDWARE;
1117 if(state == AL_PLAYING)
1118 *status |= DSBSTATUS_PLAYING | (looping ? DSBSTATUS_LOOPING : 0);
1120 LeaveCriticalSection(This->crst);
1122 return S_OK;
1125 static HRESULT WINAPI DS8Buffer_Initialize(IDirectSoundBuffer8 *iface, IDirectSound *ds, const DSBUFFERDESC *desc)
1127 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1128 DS3DBUFFER *ds3dbuffer;
1129 HRESULT hr;
1131 TRACE("(%p)->(%p, %p)\n", iface, ds, desc);
1133 EnterCriticalSection(This->crst);
1134 setALContext(This->ctx);
1136 hr = DSERR_ALREADYINITIALIZED;
1137 if(This->source)
1138 goto out;
1140 if(!This->buffer)
1142 hr = DSERR_INVALIDPARAM;
1143 if(!desc)
1145 WARN("Missing DSound buffer description\n");
1146 goto out;
1148 if(!desc->lpwfxFormat)
1150 WARN("Missing buffer format (%p)\n", This);
1151 goto out;
1153 if((desc->dwFlags&DSBCAPS_CTRL3D) && desc->lpwfxFormat->nChannels != 1)
1155 if(This->primary->parent->is_8)
1157 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
1158 * buffers */
1159 WARN("Can't create multi-channel 3D buffers\n");
1160 goto out;
1162 ERR("Multi-channel 3D sounds are not spatialized\n");
1165 hr = DS8Data_Create(&This->buffer, desc, This->primary);
1166 if(FAILED(hr))
1167 goto out;
1168 else
1170 DS8Data *buf = This->buffer;
1172 if(buf->in_type == AL_UNSIGNED_BYTE)
1173 memset(buf->data, 0x80, buf->buf_size);
1174 else
1175 memset(buf->data, 0x00, buf->buf_size);
1177 if(This->ExtAL->BufferDataStatic)
1178 This->ExtAL->BufferDataStatic(buf->buffers[0], buf->buf_format,
1179 buf->data, buf->buf_size,
1180 buf->format.Format.nSamplesPerSec);
1181 else if(This->ExtAL->BufferSamplesSOFT)
1182 This->ExtAL->BufferSamplesSOFT(buf->buffers[0],
1183 buf->format.Format.nSamplesPerSec, buf->buf_format,
1184 buf->buf_size/buf->format.Format.nBlockAlign,
1185 buf->in_chans, buf->in_type, buf->data);
1186 else if(This->ExtAL->BufferSubData)
1187 alBufferData(buf->buffers[0], buf->buf_format,
1188 buf->data, buf->buf_size,
1189 buf->format.Format.nSamplesPerSec);
1191 getALError();
1194 hr = DSERR_GENERIC;
1195 if(This->primary->nsources)
1197 This->source = This->primary->sources[--This->primary->nsources];
1198 alSourcef(This->source, AL_GAIN, 1.0f);
1199 alSourcef(This->source, AL_PITCH, 1.0f);
1200 getALError();
1202 else
1204 alGenSources(1, &This->source);
1205 if(alGetError() != AL_NO_ERROR)
1206 goto out;
1209 ds3dbuffer = &This->ds3dbuffer;
1210 ds3dbuffer->dwSize = sizeof(*ds3dbuffer);
1211 ds3dbuffer->vPosition.x = 0.0;
1212 ds3dbuffer->vPosition.y = 0.0;
1213 ds3dbuffer->vPosition.z = 0.0;
1214 ds3dbuffer->vVelocity.x = 0.0;
1215 ds3dbuffer->vVelocity.y = 0.0;
1216 ds3dbuffer->vVelocity.z = 0.0;
1217 ds3dbuffer->dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
1218 ds3dbuffer->dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
1219 ds3dbuffer->vConeOrientation.x = 0.0;
1220 ds3dbuffer->vConeOrientation.y = 0.0;
1221 ds3dbuffer->vConeOrientation.z = 1.0;
1222 ds3dbuffer->lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
1223 ds3dbuffer->flMinDistance = DS3D_DEFAULTMINDISTANCE;
1224 ds3dbuffer->flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
1225 ds3dbuffer->dwMode = DS3DMODE_NORMAL;
1227 if((This->buffer->dsbflags&DSBCAPS_CTRL3D))
1229 if(This->primary->auxslot != 0)
1231 alSource3i(This->source, AL_AUXILIARY_SEND_FILTER, This->primary->auxslot, 0, AL_FILTER_NULL);
1232 getALError();
1235 hr = IDirectSound3DBuffer_SetAllParameters(&This->IDirectSound3DBuffer_iface, ds3dbuffer, DS3D_IMMEDIATE);
1236 if(FAILED(hr))
1238 ERR("SetAllParameters failed\n");
1239 goto out;
1242 else
1244 ALuint source = This->source;
1246 if(This->primary->auxslot != 0)
1248 /* Simple hack to make reverb affect non-3D sounds too */
1249 alSource3i(source, AL_AUXILIARY_SEND_FILTER, This->primary->auxslot, 0, AL_FILTER_NULL);
1250 /*alSource3i(source, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);*/
1253 /* Non-3D sources aren't distance attenuated */
1254 This->ds3dmode = DS3DMODE_DISABLE;
1255 alSource3f(source, AL_POSITION, 0.0f, 1.0f, 0.0f);
1256 alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
1257 alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
1258 alSourcef(source, AL_CONE_OUTER_GAIN, 1.0f);
1259 alSourcef(source, AL_REFERENCE_DISTANCE, 1.0f);
1260 alSourcef(source, AL_MAX_DISTANCE, 1000.0f);
1261 alSourcef(source, AL_ROLLOFF_FACTOR, 0.0f);
1262 alSourcei(source, AL_CONE_INNER_ANGLE, 360);
1263 alSourcei(source, AL_CONE_OUTER_ANGLE, 360);
1264 alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE);
1265 getALError();
1267 hr = S_OK;
1269 out:
1270 popALContext();
1271 LeaveCriticalSection(This->crst);
1273 return hr;
1276 static HRESULT WINAPI DS8Buffer_Lock(IDirectSoundBuffer8 *iface, DWORD ofs, DWORD bytes, void **ptr1, DWORD *len1, void **ptr2, DWORD *len2, DWORD flags)
1278 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1279 HRESULT hr;
1280 DWORD remain;
1282 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, 0x%x)\n", This, ofs, bytes, ptr1, len1, ptr2, len2, flags);
1284 if(!ptr1 || !len1)
1286 WARN("Invalid pointer/len %p %p\n", ptr1, len1);
1287 return DSERR_INVALIDPARAM;
1290 EnterCriticalSection(This->crst);
1291 setALContext(This->ctx);
1293 *ptr1 = NULL;
1294 *len1 = 0;
1295 if(ptr2) *ptr2 = NULL;
1296 if(len2) *len2 = 0;
1298 hr = DSERR_INVALIDPARAM;
1299 if((flags&DSBLOCK_FROMWRITECURSOR))
1300 DS8Buffer_GetCurrentPosition(iface, NULL, &ofs);
1301 else if(ofs >= This->buffer->buf_size)
1303 WARN("Invalid ofs %u\n", ofs);
1304 goto out;
1306 if((flags&DSBLOCK_ENTIREBUFFER))
1307 bytes = This->buffer->buf_size;
1308 else if(bytes > This->buffer->buf_size)
1310 WARN("Invalid size %u\n", bytes);
1311 goto out;
1314 *ptr1 = This->buffer->data + ofs;
1315 if(ofs+bytes >= This->buffer->buf_size)
1317 *len1 = This->buffer->buf_size - ofs;
1318 remain = bytes - *len1;
1320 else
1322 *len1 = bytes;
1323 remain = 0;
1326 This->buffer->locked = TRUE;
1328 if(ptr2 && len2 && remain)
1330 *ptr2 = This->buffer->data;
1331 *len2 = remain;
1333 hr = S_OK;
1335 out:
1336 popALContext();
1337 LeaveCriticalSection(This->crst);
1338 return hr;
1341 static HRESULT WINAPI DS8Buffer_Play(IDirectSoundBuffer8 *iface, DWORD res1, DWORD prio, DWORD flags)
1343 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1344 ALint type, state = AL_STOPPED;
1345 HRESULT hr;
1346 (void)res1;
1348 TRACE("%p\n", This);
1350 EnterCriticalSection(This->crst);
1351 setALContext(This->ctx);
1353 hr = DSERR_BUFFERLOST;
1354 if(This->bufferlost)
1356 WARN("Buffer %p lost\n", This);
1357 goto out;
1360 if((This->buffer->dsbflags&DSBCAPS_LOCDEFER))
1362 if(!(This->buffer->dsbflags&(DSBCAPS_LOCHARDWARE|DSBCAPS_LOCSOFTWARE)))
1364 if(flags & DSBPLAY_LOCSOFTWARE)
1365 This->buffer->dsbflags |= DSBCAPS_LOCSOFTWARE;
1366 else
1367 This->buffer->dsbflags |= DSBCAPS_LOCHARDWARE;
1370 else if(prio)
1372 ERR("Invalid priority set for non-deferred buffer %p, %u!\n", This->buffer, prio);
1373 hr = DSERR_INVALIDPARAM;
1374 goto out;
1377 alGetSourcei(This->source, AL_SOURCE_STATE, &state);
1378 if(This->buffer->numsegs > 1)
1380 This->islooping = !!(flags&DSBPLAY_LOOPING);
1381 if(state != AL_PLAYING && This->isplaying)
1382 state = AL_PLAYING;
1384 else
1386 alGetSourcei(This->source, AL_SOURCE_TYPE, &type);
1387 alSourcei(This->source, AL_LOOPING, (flags&DSBPLAY_LOOPING) ? AL_TRUE : AL_FALSE);
1389 getALError();
1391 hr = S_OK;
1392 if(state == AL_PLAYING)
1393 goto out;
1395 /* alSourceQueueBuffers will implicitly set type to streaming */
1396 if(This->buffer->numsegs == 1)
1398 if(type != AL_STATIC)
1399 alSourcei(This->source, AL_BUFFER, This->buffer->buffers[0]);
1400 alSourcePlay(This->source);
1402 if(alGetError() != AL_NO_ERROR)
1404 ERR("Couldn't start source\n");
1405 This->curidx = (This->buffer->numsegs-1+This->curidx)%This->buffer->numsegs;
1406 alSourcei(This->source, AL_BUFFER, 0);
1407 getALError();
1408 hr = DSERR_GENERIC;
1409 goto out;
1411 This->isplaying = TRUE;
1413 if(This->nnotify)
1415 DS8Buffer_addnotify(This);
1416 DS8Buffer_starttimer(This->primary);
1418 else if(This->buffer->numsegs > 1)
1419 DS8Buffer_starttimer(This->primary);
1421 out:
1422 popALContext();
1423 LeaveCriticalSection(This->crst);
1424 return hr;
1427 static HRESULT WINAPI DS8Buffer_SetCurrentPosition(IDirectSoundBuffer8 *iface, DWORD pos)
1429 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1430 HRESULT hr;
1431 TRACE("%p\n", This);
1433 EnterCriticalSection(This->crst);
1434 setALContext(This->ctx);
1436 hr = DSERR_INVALIDPARAM;
1437 if(pos >= This->buffer->buf_size)
1438 goto out;
1440 if(This->buffer->numsegs > 1)
1442 DS8Data *buf = This->buffer;
1443 This->curidx = pos/buf->segsize;
1444 if(This->curidx >= buf->numsegs)
1445 This->curidx = buf->numsegs - 1;
1446 if(This->isplaying)
1448 alSourceStop(This->source);
1449 alSourcei(This->source, AL_BUFFER, 0);
1450 getALError();
1453 else
1454 alSourcei(This->source, AL_BYTE_OFFSET, pos);
1455 This->lastpos = pos;
1456 hr = S_OK;
1458 out:
1459 popALContext();
1460 LeaveCriticalSection(This->crst);
1461 return hr;
1464 static HRESULT WINAPI DS8Buffer_SetFormat(IDirectSoundBuffer8 *iface, const WAVEFORMATEX *wfx)
1466 /* This call only works on primary buffers */
1467 WARN("(%p)->(%p)\n", iface, wfx);
1468 return DSERR_INVALIDCALL;
1471 static HRESULT WINAPI DS8Buffer_SetVolume(IDirectSoundBuffer8 *iface, LONG vol)
1473 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1474 HRESULT hr = S_OK;
1476 TRACE("(%p)->(%d)\n", iface, vol);
1478 if(vol > DSBVOLUME_MAX || vol < DSBVOLUME_MIN)
1480 WARN("Invalid volume (%d)\n", vol);
1481 return DSERR_INVALIDPARAM;
1484 EnterCriticalSection(This->crst);
1485 if(!(This->buffer->dsbflags&DSBCAPS_CTRLVOLUME))
1486 hr = DSERR_CONTROLUNAVAIL;
1487 if(SUCCEEDED(hr))
1489 ALfloat fvol = mB_to_gain(vol);
1490 setALContext(This->ctx);
1491 alSourcef(This->source, AL_GAIN, fvol);
1492 popALContext();
1494 LeaveCriticalSection(This->crst);
1496 return hr;
1499 static HRESULT WINAPI DS8Buffer_SetPan(IDirectSoundBuffer8 *iface, LONG pan)
1501 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1502 HRESULT hr = S_OK;
1504 TRACE("(%p)->(%d)\n", iface, pan);
1506 if(pan > DSBPAN_RIGHT || pan < DSBPAN_LEFT)
1508 WARN("invalid parameter: pan = %d\n", pan);
1509 return DSERR_INVALIDPARAM;
1512 EnterCriticalSection(This->crst);
1513 if(!(This->buffer->dsbflags&DSBCAPS_CTRLPAN))
1514 hr = DSERR_CONTROLUNAVAIL;
1515 else
1517 ALfloat pos[3];
1518 pos[0] = (pan-DSBPAN_LEFT) * 2.0 / (ALfloat)(DSBPAN_RIGHT-DSBPAN_LEFT) - 1.0;
1519 /* NOTE: Strict movement along the X plane can cause the sound to jump
1520 * between left and right sharply. Using a curved path helps smooth it
1521 * out */
1522 pos[1] = sqrt(1.0 - pos[0]*pos[0]);
1523 pos[2] = 0.0;
1525 setALContext(This->ctx);
1526 alSourcefv(This->source, AL_POSITION, pos);
1527 getALError();
1528 popALContext();
1530 if(pan != 0 && This->buffer->format.Format.nChannels > 1)
1531 FIXME("Panning for multi-channel buffers is not supported\n");
1533 LeaveCriticalSection(This->crst);
1535 return hr;
1538 static HRESULT WINAPI DS8Buffer_SetFrequency(IDirectSoundBuffer8 *iface, DWORD freq)
1540 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1541 HRESULT hr = S_OK;
1543 TRACE("(%p)->(%u)\n", iface, freq);
1545 if(freq < DSBFREQUENCY_MIN || freq > DSBFREQUENCY_MAX)
1547 WARN("invalid parameter: freq = %d\n", freq);
1548 return DSERR_INVALIDPARAM;
1551 EnterCriticalSection(This->crst);
1552 if(!(This->buffer->dsbflags&DSBCAPS_CTRLFREQUENCY))
1553 hr = DSERR_CONTROLUNAVAIL;
1554 else
1556 ALfloat pitch = 1.0f;
1557 if(freq != DSBFREQUENCY_ORIGINAL)
1558 pitch = freq / (ALfloat)This->buffer->format.Format.nSamplesPerSec;
1560 setALContext(This->ctx);
1561 alSourcef(This->source, AL_PITCH, pitch);
1562 getALError();
1563 popALContext();
1565 LeaveCriticalSection(This->crst);
1566 return hr;
1569 static HRESULT WINAPI DS8Buffer_Stop(IDirectSoundBuffer8 *iface)
1571 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1572 ALint state;
1574 TRACE("(%p)->()\n", iface);
1576 EnterCriticalSection(This->crst);
1577 setALContext(This->ctx);
1579 alSourcePause(This->source);
1580 getALError();
1581 /* Mac OS X doesn't immediately report state change
1582 * if Play() is immediately called after Stop, this can be fatal,
1583 * the buffer would never be restarted
1585 do {
1586 state = AL_PAUSED;
1587 alGetSourcei(This->source, AL_SOURCE_STATE, &state);
1588 if(state != AL_PLAYING)
1589 break;
1590 Sleep(1);
1591 } while(1);
1593 This->isplaying = FALSE;
1595 popALContext();
1596 LeaveCriticalSection(This->crst);
1598 return S_OK;
1601 static HRESULT WINAPI DS8Buffer_Unlock(IDirectSoundBuffer8 *iface, void *ptr1, DWORD len1, void *ptr2, DWORD len2)
1603 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1604 DS8Data *buf = This->buffer;
1605 DWORD bufsize = buf->buf_size;
1606 DWORD_PTR ofs1, ofs2;
1607 DWORD_PTR boundary = (DWORD_PTR)buf->data;
1608 HRESULT hr;
1610 TRACE("(%p)->(%p, %u, %p, %u)\n", iface, ptr1, len1, ptr2, len2);
1612 EnterCriticalSection(This->crst);
1613 setALContext(This->ctx);
1615 This->buffer->locked = 0;
1616 hr = DSERR_INVALIDPARAM;
1618 /* Make sure offset is between boundary and boundary + bufsize */
1619 ofs1 = (DWORD_PTR)ptr1;
1620 ofs2 = (DWORD_PTR)ptr2;
1621 if(ofs1 < boundary)
1622 goto out;
1623 if(ofs2 && ofs2 != boundary)
1624 goto out;
1625 ofs1 -= boundary;
1626 ofs2 = 0;
1627 if(bufsize-ofs1 < len1 || len2 > ofs1)
1628 goto out;
1629 if(!ptr2)
1630 len2 = 0;
1632 hr = S_OK;
1633 if(!len1 && !len2)
1634 goto out;
1636 if(This->ExtAL->BufferDataStatic)
1637 goto out;
1639 if(This->ExtAL->BufferSubSamplesSOFT)
1641 WAVEFORMATEX *format = &buf->format.Format;
1643 ptr1 = (BYTE*)ptr1 - (ofs1%format->nBlockAlign);
1644 ofs1 /= format->nBlockAlign;
1645 len1 /= format->nBlockAlign;
1646 if(len1 > 0)
1647 This->ExtAL->BufferSubSamplesSOFT(buf->buffers[0], ofs1, len1,
1648 buf->in_chans, buf->in_type, ptr1);
1649 ptr2 = (BYTE*)ptr2 - (ofs2%format->nBlockAlign);
1650 ofs2 /= format->nBlockAlign;
1651 len2 /= format->nBlockAlign;
1652 if(len2 > 0)
1653 This->ExtAL->BufferSubSamplesSOFT(buf->buffers[0], ofs2, len2,
1654 buf->in_chans, buf->in_type, ptr2);
1655 getALError();
1657 else if(This->ExtAL->BufferSubData)
1659 WAVEFORMATEX *format = &buf->format.Format;
1661 len1 -= len1%format->nBlockAlign;
1662 if(len1 > 0)
1663 This->ExtAL->BufferSubData(buf->buffers[0], buf->buf_format, ptr1,
1664 ofs1, len1);
1665 len2 -= len2%format->nBlockAlign;
1666 if(len2 > 0)
1667 This->ExtAL->BufferSubData(buf->buffers[0], buf->buf_format, ptr2,
1668 ofs2, len2);
1669 getALError();
1671 else
1673 alBufferData(buf->buffers[0], buf->buf_format,
1674 buf->data, buf->buf_size,
1675 buf->format.Format.nSamplesPerSec);
1676 getALError();
1679 out:
1680 if(hr != S_OK)
1681 WARN("Invalid parameters (0x%lx,%u) (%p,%u,%p,%u)\n", boundary, bufsize, ptr1, len1, ptr2, len2);
1682 popALContext();
1683 LeaveCriticalSection(This->crst);
1684 return hr;
1687 static HRESULT WINAPI DS8Buffer_Restore(IDirectSoundBuffer8 *iface)
1689 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1690 HRESULT hr;
1692 TRACE("(%p)->()\n", iface);
1694 EnterCriticalSection(This->crst);
1695 if(This->primary->parent->prio_level < DSSCL_WRITEPRIMARY ||
1696 iface == This->primary->write_emu)
1698 This->bufferlost = 0;
1699 hr = S_OK;
1701 else
1702 hr = DSERR_BUFFERLOST;
1703 LeaveCriticalSection(This->crst);
1705 return hr;
1708 static HRESULT WINAPI DS8Buffer_SetFX(IDirectSoundBuffer8 *iface, DWORD fxcount, DSEFFECTDESC *desc, DWORD *rescodes)
1710 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1711 DWORD i;
1713 TRACE("(%p)->(%u, %p, %p)\n", This, fxcount, desc, rescodes);
1715 if(!(This->buffer->dsbflags&DSBCAPS_CTRLFX))
1717 WARN("FX control not set\n");
1718 return DSERR_CONTROLUNAVAIL;
1721 if(fxcount == 0)
1723 if(desc || rescodes)
1725 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1726 return DSERR_INVALIDPARAM;
1729 /* No effects; we can handle that */
1730 return DS_OK;
1733 if(!desc || !rescodes)
1735 WARN("NULL desc and/or result pointer specified.\n");
1736 return DSERR_INVALIDPARAM;
1739 /* We don't (currently) handle DSound effects */
1740 for(i = 0;i < fxcount;++i)
1742 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc[i].guidDSFXClass));
1743 rescodes[i] = DSFXR_FAILED;
1746 return DSERR_INVALIDPARAM;
1749 static HRESULT WINAPI DS8Buffer_AcquireResources(IDirectSoundBuffer8 *iface, DWORD flags, DWORD fxcount, DWORD *rescodes)
1751 DS8Buffer *This = impl_from_IDirectSoundBuffer8(iface);
1753 TRACE("(%p)->(%u, %u, %p)\n", This, flags, fxcount, rescodes);
1755 /* effects aren't supported at the moment.. */
1756 if(fxcount != 0 || rescodes)
1758 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1759 return DSERR_INVALIDPARAM;
1762 EnterCriticalSection(This->crst);
1763 if((This->buffer->dsbflags&DSBCAPS_LOCDEFER))
1765 This->buffer->dsbflags &= ~(DSBCAPS_LOCSOFTWARE|DSBCAPS_LOCHARDWARE);
1766 if((flags&DSBPLAY_LOCSOFTWARE))
1767 This->buffer->dsbflags |= DSBCAPS_LOCSOFTWARE;
1768 else
1769 This->buffer->dsbflags |= DSBCAPS_LOCHARDWARE;
1771 LeaveCriticalSection(This->crst);
1773 return S_OK;
1776 static HRESULT WINAPI DS8Buffer_GetObjectInPath(IDirectSoundBuffer8 *iface, REFGUID guid, DWORD idx, REFGUID rguidiface, void **ppv)
1778 FIXME("(%p)->(%s, %u, %s, %p) : stub!\n", iface, debugstr_guid(guid), idx, debugstr_guid(rguidiface), ppv);
1779 return E_NOTIMPL;
1782 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl =
1784 DS8Buffer_QueryInterface,
1785 DS8Buffer_AddRef,
1786 DS8Buffer_Release,
1787 DS8Buffer_GetCaps,
1788 DS8Buffer_GetCurrentPosition,
1789 DS8Buffer_GetFormat,
1790 DS8Buffer_GetVolume,
1791 DS8Buffer_GetPan,
1792 DS8Buffer_GetFrequency,
1793 DS8Buffer_GetStatus,
1794 DS8Buffer_Initialize,
1795 DS8Buffer_Lock,
1796 DS8Buffer_Play,
1797 DS8Buffer_SetCurrentPosition,
1798 DS8Buffer_SetFormat,
1799 DS8Buffer_SetVolume,
1800 DS8Buffer_SetPan,
1801 DS8Buffer_SetFrequency,
1802 DS8Buffer_Stop,
1803 DS8Buffer_Unlock,
1804 DS8Buffer_Restore,
1805 DS8Buffer_SetFX,
1806 DS8Buffer_AcquireResources,
1807 DS8Buffer_GetObjectInPath
1811 static HRESULT WINAPI DS8Buffer3D_QueryInterface(IDirectSound3DBuffer *iface, REFIID riid, void **ppv)
1813 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
1814 return IDirectSoundBuffer8_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppv);
1817 static ULONG WINAPI DS8Buffer3D_AddRef(IDirectSound3DBuffer *iface)
1819 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
1820 LONG ret;
1822 InterlockedIncrement(&This->all_ref);
1823 ret = InterlockedIncrement(&This->ds3d_ref);
1824 TRACE("new refcount %d\n", ret);
1826 return ret;
1829 static ULONG WINAPI DS8Buffer3D_Release(IDirectSound3DBuffer *iface)
1831 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
1832 LONG ret;
1834 ret = InterlockedDecrement(&This->ds3d_ref);
1835 TRACE("new refcount %d\n", ret);
1836 if(InterlockedDecrement(&This->all_ref) == 0)
1837 DS8Buffer_Destroy(This);
1839 return ret;
1842 static HRESULT WINAPI DS8Buffer3D_GetAllParameters(IDirectSound3DBuffer *iface, DS3DBUFFER *ds3dbuffer)
1844 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
1845 DS3DBUFFER ds3dbuf;
1846 HRESULT hr;
1848 TRACE("%p\n", This);
1850 if(!ds3dbuffer || ds3dbuffer->dwSize < sizeof(*ds3dbuffer))
1852 WARN("Invalid parameters %p %u\n", ds3dbuffer, ds3dbuffer ? ds3dbuffer->dwSize : 0);
1853 return DSERR_INVALIDPARAM;
1855 ds3dbuf.dwSize = sizeof(ds3dbuf);
1857 EnterCriticalSection(This->crst);
1858 setALContext(This->ctx);
1860 hr = IDirectSound3DBuffer_GetPosition(iface, &ds3dbuf.vPosition);
1861 if(SUCCEEDED(hr))
1862 hr = IDirectSound3DBuffer_GetVelocity(iface, &ds3dbuf.vVelocity);
1863 if(SUCCEEDED(hr))
1864 hr = IDirectSound3DBuffer_GetConeAngles(iface, &ds3dbuf.dwInsideConeAngle, &ds3dbuf.dwOutsideConeAngle);
1865 if(SUCCEEDED(hr))
1866 hr = IDirectSound3DBuffer_GetConeOrientation(iface, &ds3dbuf.vConeOrientation);
1867 if(SUCCEEDED(hr))
1868 hr = IDirectSound3DBuffer_GetConeOutsideVolume(iface, &ds3dbuf.lConeOutsideVolume);
1869 if(SUCCEEDED(hr))
1870 hr = IDirectSound3DBuffer_GetMinDistance(iface, &ds3dbuf.flMinDistance);
1871 if(SUCCEEDED(hr))
1872 hr = IDirectSound3DBuffer_GetMaxDistance(iface, &ds3dbuf.flMaxDistance);
1873 if(SUCCEEDED(hr))
1874 hr = IDirectSound3DBuffer_GetMode(iface, &ds3dbuf.dwMode);
1875 if(SUCCEEDED(hr))
1876 memcpy(ds3dbuffer, &ds3dbuf, sizeof(ds3dbuf));
1878 popALContext();
1879 LeaveCriticalSection(This->crst);
1881 return hr;
1884 static HRESULT WINAPI DS8Buffer3D_GetConeAngles(IDirectSound3DBuffer *iface, DWORD *pdwInsideConeAngle, DWORD *pdwOutsideConeAngle)
1886 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
1887 ALint inangle, outangle;
1889 TRACE("(%p)->(%p, %p)\n", This, pdwInsideConeAngle, pdwOutsideConeAngle);
1890 if(!pdwInsideConeAngle || !pdwOutsideConeAngle)
1892 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle, pdwOutsideConeAngle);
1893 return DSERR_INVALIDPARAM;
1896 EnterCriticalSection(This->crst);
1897 setALContext(This->ctx);
1899 alGetSourcei(This->source, AL_CONE_INNER_ANGLE, &inangle);
1900 alGetSourcei(This->source, AL_CONE_OUTER_ANGLE, &outangle);
1901 getALError();
1902 *pdwInsideConeAngle = inangle;
1903 *pdwOutsideConeAngle = outangle;
1905 popALContext();
1906 LeaveCriticalSection(This->crst);
1908 return S_OK;
1911 static HRESULT WINAPI DS8Buffer3D_GetConeOrientation(IDirectSound3DBuffer *iface, D3DVECTOR *orient)
1913 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
1914 ALfloat dir[3];
1916 TRACE("(%p)->(%p)\n", This, orient);
1917 if(!orient)
1919 WARN("Invalid pointer\n");
1920 return DSERR_INVALIDPARAM;
1923 EnterCriticalSection(This->crst);
1924 setALContext(This->ctx);
1926 alGetSourcefv(This->source, AL_DIRECTION, dir);
1927 getALError();
1928 orient->x = dir[0];
1929 orient->y = dir[1];
1930 orient->z = -dir[2];
1932 popALContext();
1933 LeaveCriticalSection(This->crst);
1935 return S_OK;
1938 static HRESULT WINAPI DS8Buffer3D_GetConeOutsideVolume(IDirectSound3DBuffer *iface, LONG *vol)
1940 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
1941 ALfloat gain;
1943 TRACE("(%p)->(%p)\n", This, vol);
1944 if(!vol)
1946 WARN("Invalid pointer\n");
1947 return DSERR_INVALIDPARAM;
1950 EnterCriticalSection(This->crst);
1951 setALContext(This->ctx);
1953 alGetSourcef(This->source, AL_CONE_OUTER_GAIN, &gain);
1954 getALError();
1955 *vol = gain_to_mB(gain);
1956 *vol = max(*vol, DSBVOLUME_MIN);
1957 *vol = min(*vol, DSBVOLUME_MAX);
1959 popALContext();
1960 LeaveCriticalSection(This->crst);
1961 return S_OK;
1964 static HRESULT WINAPI DS8Buffer3D_GetMaxDistance(IDirectSound3DBuffer *iface, D3DVALUE *maxdist)
1966 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
1967 ALfloat dist;
1969 TRACE("(%p)->(%p)\n", This, maxdist);
1970 if(!maxdist)
1972 WARN("Invalid pointer\n");
1973 return DSERR_INVALIDPARAM;
1976 EnterCriticalSection(This->crst);
1977 setALContext(This->ctx);
1979 alGetSourcef(This->source, AL_MAX_DISTANCE, &dist);
1980 getALError();
1981 *maxdist = dist;
1983 popALContext();
1984 LeaveCriticalSection(This->crst);
1986 return S_OK;
1989 static HRESULT WINAPI DS8Buffer3D_GetMinDistance(IDirectSound3DBuffer *iface, D3DVALUE *mindist)
1991 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
1992 ALfloat dist;
1994 TRACE("(%p)->(%p)\n", This, mindist);
1995 if(!mindist)
1997 WARN("Invalid pointer\n");
1998 return DSERR_INVALIDPARAM;
2001 EnterCriticalSection(This->crst);
2002 setALContext(This->ctx);
2004 alGetSourcef(This->source, AL_REFERENCE_DISTANCE, &dist);
2005 getALError();
2006 *mindist = dist;
2008 popALContext();
2009 LeaveCriticalSection(This->crst);
2011 return S_OK;
2014 static HRESULT WINAPI DS8Buffer3D_GetMode(IDirectSound3DBuffer *iface, DWORD *mode)
2016 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2018 TRACE("(%p)->(%p)\n", This, mode);
2019 if(!mode)
2021 WARN("Invalid pointer\n");
2022 return DSERR_INVALIDPARAM;
2025 EnterCriticalSection(This->crst);
2026 *mode = This->ds3dmode;
2027 LeaveCriticalSection(This->crst);
2029 return S_OK;
2032 static HRESULT WINAPI DS8Buffer3D_GetPosition(IDirectSound3DBuffer *iface, D3DVECTOR *pos)
2034 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2035 ALfloat alpos[3];
2037 TRACE("(%p)->(%p)\n", This, pos);
2038 if(!pos)
2040 WARN("Invalid pointer\n");
2041 return DSERR_INVALIDPARAM;
2044 EnterCriticalSection(This->crst);
2045 setALContext(This->ctx);
2047 alGetSourcefv(This->source, AL_POSITION, alpos);
2048 getALError();
2049 pos->x = alpos[0];
2050 pos->y = alpos[1];
2051 pos->z = -alpos[2];
2053 popALContext();
2054 LeaveCriticalSection(This->crst);
2056 return S_OK;
2059 static HRESULT WINAPI DS8Buffer3D_GetVelocity(IDirectSound3DBuffer *iface, D3DVECTOR *vel)
2061 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2062 ALfloat alvel[3];
2064 TRACE("(%p)->(%p)\n", This, vel);
2065 if(!vel)
2067 WARN("Invalid pointer\n");
2068 return DSERR_INVALIDPARAM;
2071 EnterCriticalSection(This->crst);
2072 setALContext(This->ctx);
2074 alGetSourcefv(This->source, AL_VELOCITY, alvel);
2075 getALError();
2076 vel->x = alvel[0];
2077 vel->y = alvel[1];
2078 vel->z = -alvel[2];
2080 popALContext();
2081 LeaveCriticalSection(This->crst);
2083 return S_OK;
2086 static HRESULT WINAPI DS8Buffer3D_SetAllParameters(IDirectSound3DBuffer *iface, const DS3DBUFFER *ds3dbuffer, DWORD apply)
2088 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2089 TRACE("(%p)->(%p, %u)\n", This, ds3dbuffer, apply);
2091 if(!ds3dbuffer || ds3dbuffer->dwSize < sizeof(*ds3dbuffer))
2093 WARN("Invalid DS3DBUFFER (%p, %u)\n", ds3dbuffer, ds3dbuffer ? ds3dbuffer->dwSize : 0);
2094 return DSERR_INVALIDPARAM;
2097 if(ds3dbuffer->dwInsideConeAngle > DS3D_MAXCONEANGLE ||
2098 ds3dbuffer->dwOutsideConeAngle > DS3D_MAXCONEANGLE)
2100 WARN("Invalid cone angles (%u, %u)\n", ds3dbuffer->dwInsideConeAngle,
2101 ds3dbuffer->dwOutsideConeAngle);
2102 return DSERR_INVALIDPARAM;
2105 if(ds3dbuffer->lConeOutsideVolume > DSBVOLUME_MAX ||
2106 ds3dbuffer->lConeOutsideVolume < DSBVOLUME_MIN)
2108 WARN("Invalid cone outside volume (%d)\n", ds3dbuffer->lConeOutsideVolume);
2109 return DSERR_INVALIDPARAM;
2112 if(ds3dbuffer->flMaxDistance < 0.0f)
2114 WARN("Invalid max distance (%f)\n", ds3dbuffer->flMaxDistance);
2115 return DSERR_INVALIDPARAM;
2118 if(ds3dbuffer->flMinDistance < 0.0f)
2120 WARN("Invalid min distance (%f)\n", ds3dbuffer->flMinDistance);
2121 return DSERR_INVALIDPARAM;
2124 if(ds3dbuffer->dwMode != DS3DMODE_NORMAL &&
2125 ds3dbuffer->dwMode != DS3DMODE_HEADRELATIVE &&
2126 ds3dbuffer->dwMode != DS3DMODE_DISABLE)
2128 WARN("Invalid mode (%u)\n", ds3dbuffer->dwMode);
2129 return DSERR_INVALIDPARAM;
2132 EnterCriticalSection(This->crst);
2133 setALContext(This->ctx);
2134 IDirectSound3DBuffer_SetPosition(iface, ds3dbuffer->vPosition.x, ds3dbuffer->vPosition.y, ds3dbuffer->vPosition.z, apply);
2135 IDirectSound3DBuffer_SetVelocity(iface, ds3dbuffer->vVelocity.x, ds3dbuffer->vVelocity.y, ds3dbuffer->vVelocity.z, apply);
2136 IDirectSound3DBuffer_SetConeAngles(iface, ds3dbuffer->dwInsideConeAngle, ds3dbuffer->dwOutsideConeAngle, apply);
2137 IDirectSound3DBuffer_SetConeOrientation(iface, ds3dbuffer->vConeOrientation.x, ds3dbuffer->vConeOrientation.y, ds3dbuffer->vConeOrientation.z, apply);
2138 IDirectSound3DBuffer_SetConeOutsideVolume(iface, ds3dbuffer->lConeOutsideVolume, apply);
2139 IDirectSound3DBuffer_SetMinDistance(iface, ds3dbuffer->flMinDistance, apply);
2140 IDirectSound3DBuffer_SetMaxDistance(iface, ds3dbuffer->flMaxDistance, apply);
2141 IDirectSound3DBuffer_SetMode(iface, ds3dbuffer->dwMode, apply);
2142 popALContext();
2143 LeaveCriticalSection(This->crst);
2145 return S_OK;
2148 static HRESULT WINAPI DS8Buffer3D_SetConeAngles(IDirectSound3DBuffer *iface, DWORD dwInsideConeAngle, DWORD dwOutsideConeAngle, DWORD apply)
2150 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2152 TRACE("(%p)->(%u, %u, %u)\n", This, dwInsideConeAngle, dwOutsideConeAngle, apply);
2153 if(dwInsideConeAngle > DS3D_MAXCONEANGLE ||
2154 dwOutsideConeAngle > DS3D_MAXCONEANGLE)
2156 WARN("Invalid cone angles (%u, %u)\n", dwInsideConeAngle, dwOutsideConeAngle);
2157 return DSERR_INVALIDPARAM;
2160 EnterCriticalSection(This->crst);
2161 if(apply == DS3D_DEFERRED)
2163 This->ds3dbuffer.dwInsideConeAngle = dwInsideConeAngle;
2164 This->ds3dbuffer.dwOutsideConeAngle = dwOutsideConeAngle;
2165 This->dirty.bit.cone_angles = 1;
2167 else
2169 setALContext(This->ctx);
2170 alSourcei(This->source, AL_CONE_INNER_ANGLE, dwInsideConeAngle);
2171 alSourcei(This->source, AL_CONE_OUTER_ANGLE, dwOutsideConeAngle);
2172 getALError();
2173 popALContext();
2175 LeaveCriticalSection(This->crst);
2177 return S_OK;
2180 static HRESULT WINAPI DS8Buffer3D_SetConeOrientation(IDirectSound3DBuffer *iface, D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD apply)
2182 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2184 TRACE("(%p)->(%f, %f, %f, %u)\n", This, x, y, z, apply);
2186 EnterCriticalSection(This->crst);
2187 if(apply == DS3D_DEFERRED)
2189 This->ds3dbuffer.vConeOrientation.x = x;
2190 This->ds3dbuffer.vConeOrientation.y = y;
2191 This->ds3dbuffer.vConeOrientation.z = z;
2192 This->dirty.bit.cone_orient = 1;
2194 else
2196 setALContext(This->ctx);
2197 alSource3f(This->source, AL_DIRECTION, x, y, -z);
2198 getALError();
2199 popALContext();
2201 LeaveCriticalSection(This->crst);
2203 return S_OK;
2206 static HRESULT WINAPI DS8Buffer3D_SetConeOutsideVolume(IDirectSound3DBuffer *iface, LONG vol, DWORD apply)
2208 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2210 TRACE("(%p)->(%u, %u)\n", This, vol, apply);
2211 if(vol < DSBVOLUME_MIN || vol > DSBVOLUME_MAX)
2213 WARN("Invalid volume (%u)\n", vol);
2214 return DSERR_INVALIDPARAM;
2217 EnterCriticalSection(This->crst);
2218 if(apply == DS3D_DEFERRED)
2220 This->ds3dbuffer.lConeOutsideVolume = vol;
2221 This->dirty.bit.cone_outsidevolume = 1;
2223 else
2225 setALContext(This->ctx);
2226 alSourcef(This->source, AL_CONE_OUTER_GAIN, mB_to_gain(vol));
2227 getALError();
2228 popALContext();
2230 LeaveCriticalSection(This->crst);
2232 return S_OK;
2235 static HRESULT WINAPI DS8Buffer3D_SetMaxDistance(IDirectSound3DBuffer *iface, D3DVALUE maxdist, DWORD apply)
2237 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2239 TRACE("(%p)->(%f, %u)\n", This, maxdist, apply);
2240 if(maxdist < 0.0f)
2242 WARN("Invalid max distance (%f)\n", maxdist);
2243 return DSERR_INVALIDPARAM;
2246 EnterCriticalSection(This->crst);
2247 if(apply == DS3D_DEFERRED)
2249 This->ds3dbuffer.flMaxDistance = maxdist;
2250 This->dirty.bit.max_distance = 1;
2252 else
2254 setALContext(This->ctx);
2255 alSourcef(This->source, AL_MAX_DISTANCE, maxdist);
2256 getALError();
2257 popALContext();
2259 LeaveCriticalSection(This->crst);
2261 return S_OK;
2264 static HRESULT WINAPI DS8Buffer3D_SetMinDistance(IDirectSound3DBuffer *iface, D3DVALUE mindist, DWORD apply)
2266 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2268 TRACE("(%p)->(%f, %u)\n", This, mindist, apply);
2269 if(mindist < 0.0f)
2271 WARN("Invalid min distance (%f)\n", mindist);
2272 return DSERR_INVALIDPARAM;
2275 EnterCriticalSection(This->crst);
2276 if(apply == DS3D_DEFERRED)
2278 This->ds3dbuffer.flMinDistance = mindist;
2279 This->dirty.bit.min_distance = 1;
2281 else
2283 setALContext(This->ctx);
2284 alSourcef(This->source, AL_REFERENCE_DISTANCE, mindist);
2285 getALError();
2286 popALContext();
2288 LeaveCriticalSection(This->crst);
2290 return S_OK;
2293 static HRESULT WINAPI DS8Buffer3D_SetMode(IDirectSound3DBuffer *iface, DWORD mode, DWORD apply)
2295 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2297 TRACE("(%p)->(%u, %u)\n", This, mode, apply);
2298 if(mode != DS3DMODE_NORMAL && mode != DS3DMODE_HEADRELATIVE &&
2299 mode != DS3DMODE_DISABLE)
2301 WARN("Invalid mode (%u)\n", mode);
2302 return DSERR_INVALIDPARAM;
2305 EnterCriticalSection(This->crst);
2306 if(apply == DS3D_DEFERRED)
2308 This->ds3dbuffer.dwMode = mode;
2309 This->dirty.bit.mode = 1;
2311 else
2313 setALContext(This->ctx);
2314 alSourcei(This->source, AL_SOURCE_RELATIVE,
2315 (mode != DS3DMODE_NORMAL) ? AL_TRUE : AL_FALSE);
2316 alSourcef(This->source, AL_ROLLOFF_FACTOR,
2317 (mode == DS3DMODE_DISABLE) ? 0.0f : This->primary->rollofffactor);
2318 This->ds3dmode = mode;
2319 getALError();
2320 popALContext();
2322 LeaveCriticalSection(This->crst);
2324 return S_OK;
2327 static HRESULT WINAPI DS8Buffer3D_SetPosition(IDirectSound3DBuffer *iface, D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD apply)
2329 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2331 TRACE("(%p)->(%f, %f, %f, %u)\n", This, x, y, z, apply);
2333 EnterCriticalSection(This->crst);
2334 if(apply == DS3D_DEFERRED)
2336 This->ds3dbuffer.vPosition.x = x;
2337 This->ds3dbuffer.vPosition.y = y;
2338 This->ds3dbuffer.vPosition.z = z;
2339 This->dirty.bit.pos = 1;
2341 else
2343 setALContext(This->ctx);
2344 alSource3f(This->source, AL_POSITION, x, y, -z);
2345 getALError();
2346 popALContext();
2348 LeaveCriticalSection(This->crst);
2350 return S_OK;
2353 static HRESULT WINAPI DS8Buffer3D_SetVelocity(IDirectSound3DBuffer *iface, D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD apply)
2355 DS8Buffer *This = impl_from_IDirectSound3DBuffer(iface);
2357 TRACE("(%p)->(%f, %f, %f, %u)\n", This, x, y, z, apply);
2359 EnterCriticalSection(This->crst);
2360 if(apply == DS3D_DEFERRED)
2362 This->ds3dbuffer.vVelocity.x = x;
2363 This->ds3dbuffer.vVelocity.y = y;
2364 This->ds3dbuffer.vVelocity.z = z;
2365 This->dirty.bit.vel = 1;
2367 else
2369 setALContext(This->ctx);
2370 alSource3f(This->source, AL_VELOCITY, x, y, -z);
2371 getALError();
2372 popALContext();
2374 LeaveCriticalSection(This->crst);
2376 return S_OK;
2379 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl =
2381 DS8Buffer3D_QueryInterface,
2382 DS8Buffer3D_AddRef,
2383 DS8Buffer3D_Release,
2384 DS8Buffer3D_GetAllParameters,
2385 DS8Buffer3D_GetConeAngles,
2386 DS8Buffer3D_GetConeOrientation,
2387 DS8Buffer3D_GetConeOutsideVolume,
2388 DS8Buffer3D_GetMaxDistance,
2389 DS8Buffer3D_GetMinDistance,
2390 DS8Buffer3D_GetMode,
2391 DS8Buffer3D_GetPosition,
2392 DS8Buffer3D_GetVelocity,
2393 DS8Buffer3D_SetAllParameters,
2394 DS8Buffer3D_SetConeAngles,
2395 DS8Buffer3D_SetConeOrientation,
2396 DS8Buffer3D_SetConeOutsideVolume,
2397 DS8Buffer3D_SetMaxDistance,
2398 DS8Buffer3D_SetMinDistance,
2399 DS8Buffer3D_SetMode,
2400 DS8Buffer3D_SetPosition,
2401 DS8Buffer3D_SetVelocity
2405 static HRESULT WINAPI DS8BufferNot_QueryInterface(IDirectSoundNotify *iface, REFIID riid, void **ppv)
2407 DS8Buffer *This = impl_from_IDirectSoundNotify(iface);
2408 return IDirectSoundBuffer8_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppv);
2411 static ULONG WINAPI DS8BufferNot_AddRef(IDirectSoundNotify *iface)
2413 DS8Buffer *This = impl_from_IDirectSoundNotify(iface);
2414 LONG ret;
2416 InterlockedIncrement(&This->all_ref);
2417 ret = InterlockedIncrement(&This->not_ref);
2418 TRACE("new refcount %d\n", ret);
2420 return ret;
2423 static ULONG WINAPI DS8BufferNot_Release(IDirectSoundNotify *iface)
2425 DS8Buffer *This = impl_from_IDirectSoundNotify(iface);
2426 LONG ret;
2428 ret = InterlockedDecrement(&This->not_ref);
2429 TRACE("new refcount %d\n", ret);
2430 if(InterlockedDecrement(&This->all_ref) == 0)
2431 DS8Buffer_Destroy(This);
2433 return ret;
2436 static HRESULT WINAPI DS8BufferNot_SetNotificationPositions(IDirectSoundNotify *iface, DWORD count, const DSBPOSITIONNOTIFY *notifications)
2438 DS8Buffer *This = impl_from_IDirectSoundNotify(iface);
2439 DSBPOSITIONNOTIFY *nots;
2440 DWORD state;
2441 HRESULT hr;
2443 EnterCriticalSection(This->crst);
2444 hr = DSERR_INVALIDPARAM;
2445 if(count && !notifications)
2446 goto out;
2448 hr = IDirectSoundBuffer8_GetStatus(&This->IDirectSoundBuffer8_iface, &state);
2449 if(FAILED(hr))
2450 goto out;
2452 hr = DSERR_INVALIDCALL;
2453 if((state&DSBSTATUS_PLAYING))
2454 goto out;
2456 if(!count)
2458 HeapFree(GetProcessHeap(), 0, This->notify);
2459 This->notify = 0;
2460 This->nnotify = 0;
2461 hr = S_OK;
2463 else
2465 DWORD i;
2467 hr = DSERR_INVALIDPARAM;
2468 for(i = 0;i < count;++i)
2470 if(notifications[i].dwOffset >= This->buffer->buf_size &&
2471 notifications[i].dwOffset != (DWORD)DSBPN_OFFSETSTOP)
2472 goto out;
2475 hr = E_OUTOFMEMORY;
2476 nots = HeapAlloc(GetProcessHeap(), 0, count*sizeof(*nots));
2477 if(!nots)
2478 goto out;
2479 memcpy(nots, notifications, count*sizeof(*nots));
2481 HeapFree(GetProcessHeap(), 0, This->notify);
2482 This->notify = nots;
2483 This->nnotify = count;
2485 hr = S_OK;
2488 out:
2489 LeaveCriticalSection(This->crst);
2490 return hr;
2493 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl =
2495 DS8BufferNot_QueryInterface,
2496 DS8BufferNot_AddRef,
2497 DS8BufferNot_Release,
2498 DS8BufferNot_SetNotificationPositions
2502 static HRESULT WINAPI DS8BufferProp_QueryInterface(IKsPropertySet *iface, REFIID riid, void **ppv)
2504 DS8Buffer *This = impl_from_IKsPropertySet(iface);
2505 return IDirectSoundBuffer8_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppv);
2508 static ULONG WINAPI DS8BufferProp_AddRef(IKsPropertySet *iface)
2510 DS8Buffer *This = impl_from_IKsPropertySet(iface);
2511 LONG ret;
2513 InterlockedIncrement(&This->all_ref);
2514 ret = InterlockedIncrement(&This->prop_ref);
2515 TRACE("new refcount %d\n", ret);
2517 return ret;
2520 static ULONG WINAPI DS8BufferProp_Release(IKsPropertySet *iface)
2522 DS8Buffer *This = impl_from_IKsPropertySet(iface);
2523 LONG ret;
2525 ret = InterlockedDecrement(&This->prop_ref);
2526 TRACE("new refcount %d\n", ret);
2527 if(InterlockedDecrement(&This->all_ref) == 0)
2528 DS8Buffer_Destroy(This);
2530 return ret;
2533 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2534 handled through secondary buffers. */
2535 static HRESULT WINAPI DS8BufferProp_Get(IKsPropertySet *iface,
2536 REFGUID guidPropSet, ULONG dwPropID,
2537 LPVOID pInstanceData, ULONG cbInstanceData,
2538 LPVOID pPropData, ULONG cbPropData,
2539 PULONG pcbReturned)
2541 DS8Buffer *This = impl_from_IKsPropertySet(iface);
2542 HRESULT hr = E_PROP_ID_UNSUPPORTED;
2544 TRACE("(%p)->(%s, %u, %p, %u, %p, %u, %p)\n", iface, debugstr_guid(guidPropSet),
2545 dwPropID, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
2547 if(!pcbReturned)
2548 return E_POINTER;
2549 *pcbReturned = 0;
2551 #if 0
2552 if(IsEqualIID(guidPropSet, &DSPROPSETID_EAX20_BufferProperties))
2555 else
2556 #endif
2558 /* Not a known buffer/source property. Pass it to the listener */
2559 hr = IKsPropertySet_Get(&This->primary->IKsPropertySet_iface, guidPropSet,
2560 dwPropID, pInstanceData, cbInstanceData, pPropData, cbPropData,
2561 pcbReturned);
2564 return hr;
2567 static HRESULT WINAPI DS8BufferProp_Set(IKsPropertySet *iface,
2568 REFGUID guidPropSet, ULONG dwPropID,
2569 LPVOID pInstanceData, ULONG cbInstanceData,
2570 LPVOID pPropData, ULONG cbPropData)
2572 DS8Buffer *This = impl_from_IKsPropertySet(iface);
2573 HRESULT hr = E_PROP_ID_UNSUPPORTED;
2575 TRACE("(%p)->(%s, %u, %p, %u, %p, %u)\n", iface, debugstr_guid(guidPropSet),
2576 dwPropID, pInstanceData, cbInstanceData, pPropData, cbPropData);
2578 #if 0
2579 if(IsEqualIID(guidPropSet, &DSPROPSETID_EAX20_BufferProperties))
2582 else
2583 #endif
2585 /* Not a known buffer/source property. Pass it to the listener */
2586 hr = IKsPropertySet_Set(&This->primary->IKsPropertySet_iface, guidPropSet,
2587 dwPropID, pInstanceData, cbInstanceData, pPropData,
2588 cbPropData);
2591 return hr;
2594 static HRESULT WINAPI DS8BufferProp_QuerySupport(IKsPropertySet *iface,
2595 REFGUID guidPropSet, ULONG dwPropID,
2596 PULONG pTypeSupport)
2598 DS8Buffer *This = impl_from_IKsPropertySet(iface);
2599 HRESULT hr = E_PROP_ID_UNSUPPORTED;
2601 TRACE("(%p)->(%s, %u, %p)\n", iface, debugstr_guid(guidPropSet), dwPropID, pTypeSupport);
2603 if(!pTypeSupport)
2604 return E_POINTER;
2605 *pTypeSupport = 0;
2607 #if 0
2608 if(IsEqualIID(guidPropSet, &DSPROPSETID_EAX20_BufferProperties))
2611 else
2612 #endif
2614 /* Not a known buffer/source property. Pass it to the listener */
2615 hr = IKsPropertySet_QuerySupport(&This->primary->IKsPropertySet_iface,
2616 guidPropSet, dwPropID, pTypeSupport);
2619 return hr;
2622 static const IKsPropertySetVtbl DS8BufferProp_Vtbl =
2624 DS8BufferProp_QueryInterface,
2625 DS8BufferProp_AddRef,
2626 DS8BufferProp_Release,
2627 DS8BufferProp_Get,
2628 DS8BufferProp_Set,
2629 DS8BufferProp_QuerySupport