gdi32: Recompute the background masks on every use to support PALETTEINDEX colors.
[wine/multimedia.git] / dlls / dsound / buffer.c
blob50fe7c91a4854fc0261b7db55eb2bbae110ae9bc
1 /* DirectSound
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
24 #define NONAMELESSSTRUCT
25 #define NONAMELESSUNION
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "mmsystem.h"
30 #include "winternl.h"
31 #include "vfwmsgs.h"
32 #include "wine/debug.h"
33 #include "dsound.h"
34 #include "dsound_private.h"
35 #include "dsconf.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
39 /*******************************************************************************
40 * IDirectSoundNotify
43 struct IDirectSoundNotifyImpl
45 /* IUnknown fields */
46 const IDirectSoundNotifyVtbl *lpVtbl;
47 LONG ref;
48 IDirectSoundBufferImpl* dsb;
51 static HRESULT IDirectSoundNotifyImpl_Create(IDirectSoundBufferImpl *dsb,
52 IDirectSoundNotifyImpl **pdsn);
53 static HRESULT IDirectSoundNotifyImpl_Destroy(IDirectSoundNotifyImpl *pdsn);
55 static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
56 LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj
57 ) {
58 IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
59 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
61 if (This->dsb == NULL) {
62 WARN("invalid parameter\n");
63 return E_INVALIDARG;
66 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER)This->dsb, riid, ppobj);
69 static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
71 IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
72 ULONG ref = InterlockedIncrement(&(This->ref));
73 TRACE("(%p) ref was %d\n", This, ref - 1);
74 return ref;
77 static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
79 IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
80 ULONG ref = InterlockedDecrement(&(This->ref));
81 TRACE("(%p) ref was %d\n", This, ref + 1);
83 if (!ref) {
84 This->dsb->notify = NULL;
85 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb);
86 HeapFree(GetProcessHeap(), 0, This);
87 TRACE("(%p) released\n", This);
89 return ref;
92 static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
93 LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
94 ) {
95 IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
96 TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
98 if (howmuch > 0 && notify == NULL) {
99 WARN("invalid parameter: notify == NULL\n");
100 return DSERR_INVALIDPARAM;
103 if (TRACE_ON(dsound)) {
104 unsigned int i;
105 for (i=0;i<howmuch;i++)
106 TRACE("notify at %d to %p\n",
107 notify[i].dwOffset,notify[i].hEventNotify);
110 if (howmuch > 0) {
111 /* Make an internal copy of the caller-supplied array.
112 * Replace the existing copy if one is already present. */
113 HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
114 This->dsb->notifies = HeapAlloc(GetProcessHeap(), 0,
115 howmuch * sizeof(DSBPOSITIONNOTIFY));
117 if (This->dsb->notifies == NULL) {
118 WARN("out of memory\n");
119 return DSERR_OUTOFMEMORY;
121 CopyMemory(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
122 This->dsb->nrofnotifies = howmuch;
123 } else {
124 HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
125 This->dsb->notifies = NULL;
126 This->dsb->nrofnotifies = 0;
129 return S_OK;
132 static const IDirectSoundNotifyVtbl dsnvt =
134 IDirectSoundNotifyImpl_QueryInterface,
135 IDirectSoundNotifyImpl_AddRef,
136 IDirectSoundNotifyImpl_Release,
137 IDirectSoundNotifyImpl_SetNotificationPositions,
140 static HRESULT IDirectSoundNotifyImpl_Create(
141 IDirectSoundBufferImpl * dsb,
142 IDirectSoundNotifyImpl **pdsn)
144 IDirectSoundNotifyImpl * dsn;
145 TRACE("(%p,%p)\n",dsb,pdsn);
147 dsn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dsn));
149 if (dsn == NULL) {
150 WARN("out of memory\n");
151 return DSERR_OUTOFMEMORY;
154 dsn->ref = 0;
155 dsn->lpVtbl = &dsnvt;
156 dsn->dsb = dsb;
157 dsb->notify = dsn;
158 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
160 *pdsn = dsn;
161 return DS_OK;
164 static HRESULT IDirectSoundNotifyImpl_Destroy(
165 IDirectSoundNotifyImpl *pdsn)
167 TRACE("(%p)\n",pdsn);
169 while (IDirectSoundNotifyImpl_Release((LPDIRECTSOUNDNOTIFY)pdsn) > 0);
171 return DS_OK;
174 /*******************************************************************************
175 * IDirectSoundBuffer
178 static inline IDirectSoundBufferImpl *impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8 *iface)
180 return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IDirectSoundBuffer8_iface);
183 static inline BOOL is_primary_buffer(IDirectSoundBufferImpl *This)
185 return This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER ? TRUE : FALSE;
188 static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(IDirectSoundBuffer8 *iface,
189 LPCWAVEFORMATEX wfex)
191 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
193 TRACE("(%p,%p)\n", iface, wfex);
195 if (is_primary_buffer(This))
196 return primarybuffer_SetFormat(This->device, wfex);
197 else {
198 WARN("not available for secondary buffers.\n");
199 return DSERR_INVALIDCALL;
203 static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(IDirectSoundBuffer8 *iface, LONG vol)
205 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
206 LONG oldVol;
208 HRESULT hres = DS_OK;
210 TRACE("(%p,%d)\n",This,vol);
212 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
213 WARN("control unavailable: This->dsbd.dwFlags = 0x%08x\n", This->dsbd.dwFlags);
214 return DSERR_CONTROLUNAVAIL;
217 if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) {
218 WARN("invalid parameter: vol = %d\n", vol);
219 return DSERR_INVALIDPARAM;
222 /* **** */
223 RtlAcquireResourceExclusive(&This->lock, TRUE);
225 if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) {
226 oldVol = This->ds3db_lVolume;
227 This->ds3db_lVolume = vol;
228 if (vol != oldVol)
229 /* recalc 3d volume, which in turn recalcs the pans */
230 DSOUND_Calc3DBuffer(This);
231 } else {
232 oldVol = This->volpan.lVolume;
233 This->volpan.lVolume = vol;
234 if (vol != oldVol)
235 DSOUND_RecalcVolPan(&(This->volpan));
238 RtlReleaseResource(&This->lock);
239 /* **** */
241 return hres;
244 static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(IDirectSoundBuffer8 *iface, LONG *vol)
246 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
248 TRACE("(%p,%p)\n",This,vol);
250 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
251 WARN("control unavailable\n");
252 return DSERR_CONTROLUNAVAIL;
255 if (vol == NULL) {
256 WARN("invalid parameter: vol == NULL\n");
257 return DSERR_INVALIDPARAM;
260 *vol = This->volpan.lVolume;
262 return DS_OK;
265 static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(IDirectSoundBuffer8 *iface, DWORD freq)
267 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
268 DWORD oldFreq;
270 TRACE("(%p,%d)\n",This,freq);
272 if (is_primary_buffer(This)) {
273 WARN("not available for primary buffers.\n");
274 return DSERR_CONTROLUNAVAIL;
277 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
278 WARN("control unavailable\n");
279 return DSERR_CONTROLUNAVAIL;
282 if (freq == DSBFREQUENCY_ORIGINAL)
283 freq = This->pwfx->nSamplesPerSec;
285 if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) {
286 WARN("invalid parameter: freq = %d\n", freq);
287 return DSERR_INVALIDPARAM;
290 /* **** */
291 RtlAcquireResourceExclusive(&This->lock, TRUE);
293 oldFreq = This->freq;
294 This->freq = freq;
295 if (freq != oldFreq) {
296 This->freqAdjust = ((DWORD64)This->freq << DSOUND_FREQSHIFT) / This->device->pwfx->nSamplesPerSec;
297 This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
298 DSOUND_RecalcFormat(This);
299 DSOUND_MixToTemporary(This, 0, This->buflen, FALSE);
302 RtlReleaseResource(&This->lock);
303 /* **** */
305 return DS_OK;
308 static HRESULT WINAPI IDirectSoundBufferImpl_Play(IDirectSoundBuffer8 *iface, DWORD reserved1,
309 DWORD reserved2, DWORD flags)
311 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
312 HRESULT hres = DS_OK;
314 TRACE("(%p,%08x,%08x,%08x)\n",This,reserved1,reserved2,flags);
316 /* **** */
317 RtlAcquireResourceExclusive(&This->lock, TRUE);
319 This->playflags = flags;
320 if (This->state == STATE_STOPPED) {
321 This->leadin = TRUE;
322 This->state = STATE_STARTING;
323 } else if (This->state == STATE_STOPPING)
324 This->state = STATE_PLAYING;
326 RtlReleaseResource(&This->lock);
327 /* **** */
329 return hres;
332 static HRESULT WINAPI IDirectSoundBufferImpl_Stop(IDirectSoundBuffer8 *iface)
334 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
335 HRESULT hres = DS_OK;
337 TRACE("(%p)\n",This);
339 /* **** */
340 RtlAcquireResourceExclusive(&This->lock, TRUE);
342 if (This->state == STATE_PLAYING)
343 This->state = STATE_STOPPING;
344 else if (This->state == STATE_STARTING)
346 This->state = STATE_STOPPED;
347 DSOUND_CheckEvent(This, 0, 0);
350 RtlReleaseResource(&This->lock);
351 /* **** */
353 return hres;
356 static ULONG WINAPI IDirectSoundBufferImpl_AddRef(IDirectSoundBuffer8 *iface)
358 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
359 ULONG ref = InterlockedIncrement(&This->ref);
361 TRACE("(%p) ref was %d\n", This, ref - 1);
363 if(ref == 1)
364 InterlockedIncrement(&This->numIfaces);
366 return ref;
369 static ULONG WINAPI IDirectSoundBufferImpl_Release(IDirectSoundBuffer8 *iface)
371 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
372 ULONG ref = InterlockedDecrement(&This->ref);
374 TRACE("(%p) ref was %d\n", This, ref + 1);
376 if (!ref && !InterlockedDecrement(&This->numIfaces)) {
377 if (is_primary_buffer(This))
378 primarybuffer_destroy(This);
379 else
380 secondarybuffer_destroy(This);
382 return ref;
385 static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(IDirectSoundBuffer8 *iface,
386 DWORD *playpos, DWORD *writepos)
388 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
389 DWORD pos;
391 TRACE("(%p,%p,%p)\n",This,playpos,writepos);
393 RtlAcquireResourceShared(&This->lock, TRUE);
395 pos = This->sec_mixpos;
397 /* sanity */
398 if (pos >= This->buflen){
399 FIXME("Bad play position. playpos: %d, buflen: %d\n", pos, This->buflen);
400 pos %= This->buflen;
403 if (playpos)
404 *playpos = pos;
405 if (writepos)
406 *writepos = pos;
408 if (writepos && This->state != STATE_STOPPED) {
409 /* apply the documented 10ms lead to writepos */
410 *writepos += This->writelead;
411 *writepos %= This->buflen;
414 RtlReleaseResource(&This->lock);
416 TRACE("playpos = %d, writepos = %d, buflen=%d (%p, time=%d)\n",
417 playpos?*playpos:-1, writepos?*writepos:-1, This->buflen, This, GetTickCount());
419 return DS_OK;
422 static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus(IDirectSoundBuffer8 *iface, DWORD *status)
424 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
426 TRACE("(%p,%p), thread is %04x\n",This,status,GetCurrentThreadId());
428 if (status == NULL) {
429 WARN("invalid parameter: status = NULL\n");
430 return DSERR_INVALIDPARAM;
433 *status = 0;
434 RtlAcquireResourceShared(&This->lock, TRUE);
435 if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) {
436 *status |= DSBSTATUS_PLAYING;
437 if (This->playflags & DSBPLAY_LOOPING)
438 *status |= DSBSTATUS_LOOPING;
440 RtlReleaseResource(&This->lock);
442 TRACE("status=%x\n", *status);
443 return DS_OK;
447 static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat(IDirectSoundBuffer8 *iface,
448 LPWAVEFORMATEX lpwf, DWORD wfsize, DWORD *wfwritten)
450 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
451 DWORD size;
453 TRACE("(%p,%p,%d,%p)\n",This,lpwf,wfsize,wfwritten);
455 size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
457 if (lpwf) { /* NULL is valid */
458 if (wfsize >= size) {
459 CopyMemory(lpwf,This->pwfx,size);
460 if (wfwritten)
461 *wfwritten = size;
462 } else {
463 WARN("invalid parameter: wfsize too small\n");
464 CopyMemory(lpwf,This->pwfx,wfsize);
465 if (wfwritten)
466 *wfwritten = wfsize;
467 return DSERR_INVALIDPARAM;
469 } else {
470 if (wfwritten)
471 *wfwritten = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
472 else {
473 WARN("invalid parameter: wfwritten == NULL\n");
474 return DSERR_INVALIDPARAM;
478 return DS_OK;
481 static HRESULT WINAPI IDirectSoundBufferImpl_Lock(IDirectSoundBuffer8 *iface, DWORD writecursor,
482 DWORD writebytes, void **lplpaudioptr1, DWORD *audiobytes1, void **lplpaudioptr2,
483 DWORD *audiobytes2, DWORD flags)
485 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
486 HRESULT hres = DS_OK;
488 TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n", This, writecursor, writebytes, lplpaudioptr1,
489 audiobytes1, lplpaudioptr2, audiobytes2, flags, GetTickCount());
491 if (!audiobytes1)
492 return DSERR_INVALIDPARAM;
494 /* when this flag is set, writecursor is meaningless and must be calculated */
495 if (flags & DSBLOCK_FROMWRITECURSOR) {
496 /* GetCurrentPosition does too much magic to duplicate here */
497 hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writecursor);
498 if (hres != DS_OK) {
499 WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n");
500 return hres;
504 /* when this flag is set, writebytes is meaningless and must be set */
505 if (flags & DSBLOCK_ENTIREBUFFER)
506 writebytes = This->buflen;
508 if (writecursor >= This->buflen) {
509 WARN("Invalid parameter, writecursor: %u >= buflen: %u\n",
510 writecursor, This->buflen);
511 return DSERR_INVALIDPARAM;
514 if (writebytes > This->buflen) {
515 WARN("Invalid parameter, writebytes: %u > buflen: %u\n",
516 writebytes, This->buflen);
517 return DSERR_INVALIDPARAM;
520 /* **** */
521 RtlAcquireResourceShared(&This->lock, TRUE);
523 if (writecursor+writebytes <= This->buflen) {
524 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
525 if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
526 WARN("Overwriting mixing position, case 1\n");
527 *audiobytes1 = writebytes;
528 if (lplpaudioptr2)
529 *(LPBYTE*)lplpaudioptr2 = NULL;
530 if (audiobytes2)
531 *audiobytes2 = 0;
532 TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n",
533 *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
534 TRACE("->%d.0\n",writebytes);
535 } else {
536 DWORD remainder = writebytes + writecursor - This->buflen;
537 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
538 *audiobytes1 = This->buflen-writecursor;
539 if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
540 WARN("Overwriting mixing position, case 2\n");
541 if (lplpaudioptr2)
542 *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
543 if (audiobytes2)
544 *audiobytes2 = writebytes-(This->buflen-writecursor);
545 if (audiobytes2 && This->sec_mixpos < remainder && This->state == STATE_PLAYING)
546 WARN("Overwriting mixing position, case 3\n");
547 TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
550 RtlReleaseResource(&This->lock);
551 /* **** */
553 return DS_OK;
556 static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(IDirectSoundBuffer8 *iface,
557 DWORD newpos)
559 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
560 HRESULT hres = DS_OK;
561 DWORD oldpos;
563 TRACE("(%p,%d)\n",This,newpos);
565 /* **** */
566 RtlAcquireResourceExclusive(&This->lock, TRUE);
568 oldpos = This->sec_mixpos;
570 /* start mixing from this new location instead */
571 newpos %= This->buflen;
572 newpos -= newpos%This->pwfx->nBlockAlign;
573 This->sec_mixpos = newpos;
575 /* at this point, do not attempt to reset buffers, mess with primary mix position,
576 or anything like that to reduce latency. The data already prebuffered cannot be changed */
578 /* position HW buffer if applicable, else just start mixing from new location instead */
579 if (oldpos != newpos)
580 /* FIXME: Perhaps add a call to DSOUND_MixToTemporary here? Not sure it's needed */
581 This->buf_mixpos = DSOUND_secpos_to_bufpos(This, newpos, 0, NULL);
583 RtlReleaseResource(&This->lock);
584 /* **** */
586 return hres;
589 static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(IDirectSoundBuffer8 *iface, LONG pan)
591 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
592 HRESULT hres = DS_OK;
594 TRACE("(%p,%d)\n",This,pan);
596 if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) {
597 WARN("invalid parameter: pan = %d\n", pan);
598 return DSERR_INVALIDPARAM;
601 /* You cannot use both pan and 3D controls */
602 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
603 (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) {
604 WARN("control unavailable\n");
605 return DSERR_CONTROLUNAVAIL;
608 /* **** */
609 RtlAcquireResourceExclusive(&This->lock, TRUE);
611 if (This->volpan.lPan != pan) {
612 This->volpan.lPan = pan;
613 DSOUND_RecalcVolPan(&(This->volpan));
616 RtlReleaseResource(&This->lock);
617 /* **** */
619 return hres;
622 static HRESULT WINAPI IDirectSoundBufferImpl_GetPan(IDirectSoundBuffer8 *iface, LONG *pan)
624 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
626 TRACE("(%p,%p)\n",This,pan);
628 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
629 WARN("control unavailable\n");
630 return DSERR_CONTROLUNAVAIL;
633 if (pan == NULL) {
634 WARN("invalid parameter: pan = NULL\n");
635 return DSERR_INVALIDPARAM;
638 *pan = This->volpan.lPan;
640 return DS_OK;
643 static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(IDirectSoundBuffer8 *iface, void *p1, DWORD x1,
644 void *p2, DWORD x2)
646 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface), *iter;
647 HRESULT hres = DS_OK;
649 TRACE("(%p,%p,%d,%p,%d)\n", This,p1,x1,p2,x2);
651 if (!p2)
652 x2 = 0;
654 if((p1 && ((BYTE*)p1 < This->buffer->memory ||
655 (BYTE*)p1 >= This->buffer->memory + This->buflen)) ||
656 (p2 && ((BYTE*)p2 < This->buffer->memory ||
657 (BYTE*)p2 >= This->buffer->memory + This->buflen)))
658 return DSERR_INVALIDPARAM;
660 if (x1 || x2)
662 RtlAcquireResourceShared(&This->device->buffer_list_lock, TRUE);
663 LIST_FOR_EACH_ENTRY(iter, &This->buffer->buffers, IDirectSoundBufferImpl, entry )
665 RtlAcquireResourceShared(&iter->lock, TRUE);
666 if (x1)
668 if(x1 + (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory > iter->buflen)
669 hres = DSERR_INVALIDPARAM;
670 else
671 DSOUND_MixToTemporary(iter, (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory, x1, FALSE);
673 if (x2)
674 DSOUND_MixToTemporary(iter, 0, x2, FALSE);
675 RtlReleaseResource(&iter->lock);
677 RtlReleaseResource(&This->device->buffer_list_lock);
680 return hres;
683 static HRESULT WINAPI IDirectSoundBufferImpl_Restore(IDirectSoundBuffer8 *iface)
685 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
687 FIXME("(%p):stub\n",This);
688 return DS_OK;
691 static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(IDirectSoundBuffer8 *iface, DWORD *freq)
693 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
695 TRACE("(%p,%p)\n",This,freq);
697 if (freq == NULL) {
698 WARN("invalid parameter: freq = NULL\n");
699 return DSERR_INVALIDPARAM;
702 *freq = This->freq;
703 TRACE("-> %d\n", *freq);
705 return DS_OK;
708 static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(IDirectSoundBuffer8 *iface, DWORD dwEffectsCount,
709 LPDSEFFECTDESC pDSFXDesc, DWORD *pdwResultCodes)
711 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
712 DWORD u;
714 FIXME("(%p,%u,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
716 if (pdwResultCodes)
717 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
719 WARN("control unavailable\n");
720 return DSERR_CONTROLUNAVAIL;
723 static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(IDirectSoundBuffer8 *iface,
724 DWORD dwFlags, DWORD dwEffectsCount, DWORD *pdwResultCodes)
726 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
727 DWORD u;
729 FIXME("(%p,%08u,%u,%p): stub, faking success\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
731 if (pdwResultCodes)
732 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
734 WARN("control unavailable\n");
735 return DS_OK;
738 static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(IDirectSoundBuffer8 *iface,
739 REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, void **ppObject)
741 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
743 FIXME("(%p,%s,%u,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
745 WARN("control unavailable\n");
746 return DSERR_CONTROLUNAVAIL;
749 static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(IDirectSoundBuffer8 *iface,
750 IDirectSound *dsound, LPCDSBUFFERDESC dbsd)
752 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
754 WARN("(%p) already initialized\n", This);
755 return DSERR_ALREADYINITIALIZED;
758 static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(IDirectSoundBuffer8 *iface, LPDSBCAPS caps)
760 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
762 TRACE("(%p)->(%p)\n",This,caps);
764 if (caps == NULL) {
765 WARN("invalid parameter: caps == NULL\n");
766 return DSERR_INVALIDPARAM;
769 if (caps->dwSize < sizeof(*caps)) {
770 WARN("invalid parameter: caps->dwSize = %d\n",caps->dwSize);
771 return DSERR_INVALIDPARAM;
774 caps->dwFlags = This->dsbd.dwFlags;
775 caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
777 caps->dwBufferBytes = This->buflen;
779 /* According to windows, this is zero*/
780 caps->dwUnlockTransferRate = 0;
781 caps->dwPlayCpuOverhead = 0;
783 return DS_OK;
786 static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(IDirectSoundBuffer8 *iface, REFIID riid,
787 void **ppobj)
789 IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
791 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
793 if (ppobj == NULL) {
794 WARN("invalid parameter\n");
795 return E_INVALIDARG;
798 *ppobj = NULL; /* assume failure */
800 if ( IsEqualGUID(riid, &IID_IUnknown) ||
801 IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
802 IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
803 IDirectSoundBuffer8_AddRef(iface);
804 *ppobj = iface;
805 return S_OK;
808 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
809 if (!This->notify)
810 IDirectSoundNotifyImpl_Create(This, &(This->notify));
811 if (This->notify) {
812 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
813 *ppobj = This->notify;
814 return S_OK;
816 WARN("IID_IDirectSoundNotify\n");
817 return E_NOINTERFACE;
820 if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
821 if (!This->ds3db)
822 IDirectSound3DBufferImpl_Create(This, &(This->ds3db));
823 if (This->ds3db) {
824 IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->ds3db);
825 *ppobj = This->ds3db;
826 return S_OK;
828 WARN("IID_IDirectSound3DBuffer\n");
829 return E_NOINTERFACE;
832 if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
833 ERR("app requested IDirectSound3DListener on secondary buffer\n");
834 return E_NOINTERFACE;
837 if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
838 if (!This->iks)
839 IKsBufferPropertySetImpl_Create(This, &(This->iks));
840 if (This->iks) {
841 IKsPropertySet_AddRef((LPKSPROPERTYSET)This->iks);
842 *ppobj = This->iks;
843 return S_OK;
845 WARN("IID_IKsPropertySet\n");
846 return E_NOINTERFACE;
849 FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
851 return E_NOINTERFACE;
854 static const IDirectSoundBuffer8Vtbl dsbvt =
856 IDirectSoundBufferImpl_QueryInterface,
857 IDirectSoundBufferImpl_AddRef,
858 IDirectSoundBufferImpl_Release,
859 IDirectSoundBufferImpl_GetCaps,
860 IDirectSoundBufferImpl_GetCurrentPosition,
861 IDirectSoundBufferImpl_GetFormat,
862 IDirectSoundBufferImpl_GetVolume,
863 IDirectSoundBufferImpl_GetPan,
864 IDirectSoundBufferImpl_GetFrequency,
865 IDirectSoundBufferImpl_GetStatus,
866 IDirectSoundBufferImpl_Initialize,
867 IDirectSoundBufferImpl_Lock,
868 IDirectSoundBufferImpl_Play,
869 IDirectSoundBufferImpl_SetCurrentPosition,
870 IDirectSoundBufferImpl_SetFormat,
871 IDirectSoundBufferImpl_SetVolume,
872 IDirectSoundBufferImpl_SetPan,
873 IDirectSoundBufferImpl_SetFrequency,
874 IDirectSoundBufferImpl_Stop,
875 IDirectSoundBufferImpl_Unlock,
876 IDirectSoundBufferImpl_Restore,
877 IDirectSoundBufferImpl_SetFX,
878 IDirectSoundBufferImpl_AcquireResources,
879 IDirectSoundBufferImpl_GetObjectInPath
882 HRESULT IDirectSoundBufferImpl_Create(
883 DirectSoundDevice * device,
884 IDirectSoundBufferImpl **pdsb,
885 LPCDSBUFFERDESC dsbd)
887 IDirectSoundBufferImpl *dsb;
888 LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
889 HRESULT err = DS_OK;
890 DWORD capf = 0;
891 TRACE("(%p,%p,%p)\n",device,pdsb,dsbd);
893 if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
894 WARN("invalid parameter: dsbd->dwBufferBytes = %d\n", dsbd->dwBufferBytes);
895 *pdsb = NULL;
896 return DSERR_INVALIDPARAM; /* FIXME: which error? */
899 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
901 if (dsb == 0) {
902 WARN("out of memory\n");
903 *pdsb = NULL;
904 return DSERR_OUTOFMEMORY;
907 TRACE("Created buffer at %p\n", dsb);
909 dsb->ref = 1;
910 dsb->numIfaces = 1;
911 dsb->device = device;
912 dsb->IDirectSoundBuffer8_iface.lpVtbl = &dsbvt;
913 dsb->iks = NULL;
915 /* size depends on version */
916 CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize);
918 dsb->pwfx = DSOUND_CopyFormat(wfex);
919 if (dsb->pwfx == NULL) {
920 HeapFree(GetProcessHeap(),0,dsb);
921 *pdsb = NULL;
922 return DSERR_OUTOFMEMORY;
925 if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign)
926 dsb->buflen = dsbd->dwBufferBytes +
927 (dsbd->lpwfxFormat->nBlockAlign -
928 (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign));
929 else
930 dsb->buflen = dsbd->dwBufferBytes;
932 dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
933 dsb->notify = NULL;
934 dsb->notifies = NULL;
935 dsb->nrofnotifies = 0;
937 /* Check necessary hardware mixing capabilities */
938 if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
939 else capf |= DSCAPS_SECONDARYMONO;
940 if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
941 else capf |= DSCAPS_SECONDARY8BIT;
943 TRACE("capf = 0x%08x, device->drvcaps.dwFlags = 0x%08x\n", capf, device->drvcaps.dwFlags);
945 /* Allocate an empty buffer */
946 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
947 if (dsb->buffer == NULL) {
948 WARN("out of memory\n");
949 HeapFree(GetProcessHeap(),0,dsb->pwfx);
950 HeapFree(GetProcessHeap(),0,dsb);
951 *pdsb = NULL;
952 return DSERR_OUTOFMEMORY;
955 /* Allocate system memory for buffer */
956 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
957 if (dsb->buffer->memory == NULL) {
958 WARN("out of memory\n");
959 HeapFree(GetProcessHeap(),0,dsb->pwfx);
960 HeapFree(GetProcessHeap(),0,dsb->buffer);
961 HeapFree(GetProcessHeap(),0,dsb);
962 *pdsb = NULL;
963 return DSERR_OUTOFMEMORY;
966 dsb->buffer->ref = 1;
967 list_init(&dsb->buffer->buffers);
968 list_add_head(&dsb->buffer->buffers, &dsb->entry);
969 FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0);
971 /* It's not necessary to initialize values to zero since */
972 /* we allocated this structure with HEAP_ZERO_MEMORY... */
973 dsb->buf_mixpos = dsb->sec_mixpos = 0;
974 dsb->state = STATE_STOPPED;
976 dsb->freqAdjust = ((DWORD64)dsb->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec;
977 dsb->nAvgBytesPerSec = dsb->freq *
978 dsbd->lpwfxFormat->nBlockAlign;
980 /* calculate fragment size and write lead */
981 DSOUND_RecalcFormat(dsb);
983 if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
984 dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
985 dsb->ds3db_ds3db.vPosition.x = 0.0;
986 dsb->ds3db_ds3db.vPosition.y = 0.0;
987 dsb->ds3db_ds3db.vPosition.z = 0.0;
988 dsb->ds3db_ds3db.vVelocity.x = 0.0;
989 dsb->ds3db_ds3db.vVelocity.y = 0.0;
990 dsb->ds3db_ds3db.vVelocity.z = 0.0;
991 dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
992 dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
993 dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
994 dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
995 dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
996 dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
997 dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
998 dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
999 dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
1001 dsb->ds3db_need_recalc = FALSE;
1002 DSOUND_Calc3DBuffer(dsb);
1003 } else
1004 DSOUND_RecalcVolPan(&(dsb->volpan));
1006 RtlInitializeResource(&dsb->lock);
1008 /* register buffer if not primary */
1009 if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
1010 err = DirectSoundDevice_AddBuffer(device, dsb);
1011 if (err != DS_OK) {
1012 HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
1013 HeapFree(GetProcessHeap(),0,dsb->buffer);
1014 RtlDeleteResource(&dsb->lock);
1015 HeapFree(GetProcessHeap(),0,dsb->pwfx);
1016 HeapFree(GetProcessHeap(),0,dsb);
1017 dsb = NULL;
1021 *pdsb = dsb;
1022 return err;
1025 void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
1027 DirectSoundDevice_RemoveBuffer(This->device, This);
1028 RtlDeleteResource(&This->lock);
1030 This->buffer->ref--;
1031 list_remove(&This->entry);
1032 if (This->buffer->ref == 0) {
1033 HeapFree(GetProcessHeap(), 0, This->buffer->memory);
1034 HeapFree(GetProcessHeap(), 0, This->buffer);
1037 HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
1038 HeapFree(GetProcessHeap(), 0, This->notifies);
1039 HeapFree(GetProcessHeap(), 0, This->pwfx);
1040 HeapFree(GetProcessHeap(), 0, This);
1042 TRACE("(%p) released\n", This);
1045 HRESULT IDirectSoundBufferImpl_Destroy(
1046 IDirectSoundBufferImpl *pdsb)
1048 TRACE("(%p)\n",pdsb);
1050 /* This keeps the *_Destroy functions from possibly deleting
1051 * this object until it is ready to be deleted */
1052 InterlockedIncrement(&pdsb->numIfaces);
1054 if (pdsb->iks) {
1055 WARN("iks not NULL\n");
1056 IKsBufferPropertySetImpl_Destroy(pdsb->iks);
1057 pdsb->iks = NULL;
1060 if (pdsb->ds3db) {
1061 WARN("ds3db not NULL\n");
1062 IDirectSound3DBufferImpl_Destroy(pdsb->ds3db);
1063 pdsb->ds3db = NULL;
1066 if (pdsb->notify) {
1067 WARN("notify not NULL\n");
1068 IDirectSoundNotifyImpl_Destroy(pdsb->notify);
1069 pdsb->notify = NULL;
1072 secondarybuffer_destroy(pdsb);
1074 return S_OK;
1077 HRESULT IDirectSoundBufferImpl_Duplicate(
1078 DirectSoundDevice *device,
1079 IDirectSoundBufferImpl **ppdsb,
1080 IDirectSoundBufferImpl *pdsb)
1082 IDirectSoundBufferImpl *dsb;
1083 HRESULT hres = DS_OK;
1084 TRACE("(%p,%p,%p)\n", device, ppdsb, pdsb);
1086 dsb = HeapAlloc(GetProcessHeap(),0,sizeof(*dsb));
1087 if (dsb == NULL) {
1088 WARN("out of memory\n");
1089 *ppdsb = NULL;
1090 return DSERR_OUTOFMEMORY;
1092 CopyMemory(dsb, pdsb, sizeof(*dsb));
1094 dsb->pwfx = DSOUND_CopyFormat(pdsb->pwfx);
1095 if (dsb->pwfx == NULL) {
1096 HeapFree(GetProcessHeap(),0,dsb);
1097 *ppdsb = NULL;
1098 return DSERR_OUTOFMEMORY;
1101 dsb->buffer->ref++;
1102 list_add_head(&dsb->buffer->buffers, &dsb->entry);
1103 dsb->ref = 1;
1104 dsb->numIfaces = 1;
1105 dsb->state = STATE_STOPPED;
1106 dsb->buf_mixpos = dsb->sec_mixpos = 0;
1107 dsb->notify = NULL;
1108 dsb->notifies = NULL;
1109 dsb->nrofnotifies = 0;
1110 dsb->device = device;
1111 dsb->ds3db = NULL;
1112 dsb->iks = NULL; /* FIXME? */
1113 dsb->tmp_buffer = NULL;
1114 DSOUND_RecalcFormat(dsb);
1115 DSOUND_MixToTemporary(dsb, 0, dsb->buflen, FALSE);
1117 RtlInitializeResource(&dsb->lock);
1119 /* register buffer */
1120 hres = DirectSoundDevice_AddBuffer(device, dsb);
1121 if (hres != DS_OK) {
1122 RtlDeleteResource(&dsb->lock);
1123 HeapFree(GetProcessHeap(),0,dsb->tmp_buffer);
1124 list_remove(&dsb->entry);
1125 dsb->buffer->ref--;
1126 HeapFree(GetProcessHeap(),0,dsb->pwfx);
1127 HeapFree(GetProcessHeap(),0,dsb);
1128 dsb = NULL;
1131 *ppdsb = dsb;
1132 return hres;
1135 /*******************************************************************************
1136 * IKsBufferPropertySet
1139 /* IUnknown methods */
1140 static HRESULT WINAPI IKsBufferPropertySetImpl_QueryInterface(
1141 LPKSPROPERTYSET iface,
1142 REFIID riid,
1143 LPVOID *ppobj )
1145 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1146 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1148 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
1151 static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)
1153 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1154 ULONG ref = InterlockedIncrement(&(This->ref));
1155 TRACE("(%p) ref was %d\n", This, ref - 1);
1156 return ref;
1159 static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
1161 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1162 ULONG ref = InterlockedDecrement(&(This->ref));
1163 TRACE("(%p) ref was %d\n", This, ref + 1);
1165 if (!ref) {
1166 This->dsb->iks = 0;
1167 IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
1168 HeapFree(GetProcessHeap(), 0, This);
1169 TRACE("(%p) released\n", This);
1171 return ref;
1174 static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
1175 LPKSPROPERTYSET iface,
1176 REFGUID guidPropSet,
1177 ULONG dwPropID,
1178 LPVOID pInstanceData,
1179 ULONG cbInstanceData,
1180 LPVOID pPropData,
1181 ULONG cbPropData,
1182 PULONG pcbReturned )
1184 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1186 TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
1187 This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1189 return E_PROP_ID_UNSUPPORTED;
1192 static HRESULT WINAPI IKsBufferPropertySetImpl_Set(
1193 LPKSPROPERTYSET iface,
1194 REFGUID guidPropSet,
1195 ULONG dwPropID,
1196 LPVOID pInstanceData,
1197 ULONG cbInstanceData,
1198 LPVOID pPropData,
1199 ULONG cbPropData )
1201 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1203 TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1205 return E_PROP_ID_UNSUPPORTED;
1208 static HRESULT WINAPI IKsBufferPropertySetImpl_QuerySupport(
1209 LPKSPROPERTYSET iface,
1210 REFGUID guidPropSet,
1211 ULONG dwPropID,
1212 PULONG pTypeSupport )
1214 IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1216 TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1218 return E_PROP_ID_UNSUPPORTED;
1221 static const IKsPropertySetVtbl iksbvt = {
1222 IKsBufferPropertySetImpl_QueryInterface,
1223 IKsBufferPropertySetImpl_AddRef,
1224 IKsBufferPropertySetImpl_Release,
1225 IKsBufferPropertySetImpl_Get,
1226 IKsBufferPropertySetImpl_Set,
1227 IKsBufferPropertySetImpl_QuerySupport
1230 HRESULT IKsBufferPropertySetImpl_Create(
1231 IDirectSoundBufferImpl *dsb,
1232 IKsBufferPropertySetImpl **piks)
1234 IKsBufferPropertySetImpl *iks;
1235 TRACE("(%p,%p)\n",dsb,piks);
1236 *piks = NULL;
1238 iks = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks));
1239 if (iks == 0) {
1240 WARN("out of memory\n");
1241 *piks = NULL;
1242 return DSERR_OUTOFMEMORY;
1245 iks->ref = 0;
1246 iks->dsb = dsb;
1247 dsb->iks = iks;
1248 iks->lpVtbl = &iksbvt;
1250 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
1252 *piks = iks;
1253 return S_OK;
1256 HRESULT IKsBufferPropertySetImpl_Destroy(
1257 IKsBufferPropertySetImpl *piks)
1259 TRACE("(%p)\n",piks);
1261 while (IKsBufferPropertySetImpl_Release((LPKSPROPERTYSET)piks) > 0);
1263 return S_OK;