~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/dsound/buffer.c

Version: ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*                      DirectSound
  2  *
  3  * Copyright 1998 Marcus Meissner
  4  * Copyright 1998 Rob Riggs
  5  * Copyright 2000-2002 TransGaming Technologies, Inc.
  6  *
  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.
 11  *
 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.
 16  *
 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
 20  */
 21 
 22 #include <stdarg.h>
 23 
 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"
 36 
 37 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
 38 
 39 /*******************************************************************************
 40  *              IDirectSoundNotify
 41  */
 42 
 43 static inline struct IDirectSoundBufferImpl *impl_from_IDirectSoundNotify(IDirectSoundNotify *iface)
 44 {
 45     return CONTAINING_RECORD(iface, struct IDirectSoundBufferImpl, IDirectSoundNotify_iface);
 46 }
 47 
 48 static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(IDirectSoundNotify *iface, REFIID riid,
 49         void **ppobj)
 50 {
 51     IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
 52 
 53     TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj);
 54 
 55     return IDirectSoundBuffer8_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppobj);
 56 }
 57 
 58 static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(IDirectSoundNotify *iface)
 59 {
 60     IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
 61     ULONG ref = InterlockedIncrement(&This->refn);
 62 
 63     TRACE("(%p) ref was %d\n", This, ref - 1);
 64 
 65     if(ref == 1)
 66         InterlockedIncrement(&This->numIfaces);
 67 
 68     return ref;
 69 }
 70 
 71 static ULONG WINAPI IDirectSoundNotifyImpl_Release(IDirectSoundNotify *iface)
 72 {
 73     IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
 74     ULONG ref = InterlockedDecrement(&This->refn);
 75 
 76     TRACE("(%p) ref was %d\n", This, ref + 1);
 77 
 78     if (!ref && !InterlockedDecrement(&This->numIfaces))
 79         secondarybuffer_destroy(This);
 80 
 81     return ref;
 82 }
 83 
 84 static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(IDirectSoundNotify *iface,
 85         DWORD howmuch, const DSBPOSITIONNOTIFY *notify)
 86 {
 87         IDirectSoundBufferImpl *This = impl_from_IDirectSoundNotify(iface);
 88 
 89         TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
 90 
 91         if (howmuch > 0 && notify == NULL) {
 92             WARN("invalid parameter: notify == NULL\n");
 93             return DSERR_INVALIDPARAM;
 94         }
 95 
 96         if (TRACE_ON(dsound)) {
 97             unsigned int        i;
 98             for (i=0;i<howmuch;i++)
 99                 TRACE("notify at %d to %p\n",
100                     notify[i].dwOffset,notify[i].hEventNotify);
101         }
102 
103         if (howmuch > 0) {
104             /* Make an internal copy of the caller-supplied array.
105              * Replace the existing copy if one is already present. */
106             HeapFree(GetProcessHeap(), 0, This->notifies);
107             This->notifies = HeapAlloc(GetProcessHeap(), 0,
108                         howmuch * sizeof(DSBPOSITIONNOTIFY));
109 
110             if (This->notifies == NULL) {
111                     WARN("out of memory\n");
112                     return DSERR_OUTOFMEMORY;
113             }
114             CopyMemory(This->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
115             This->nrofnotifies = howmuch;
116         } else {
117            HeapFree(GetProcessHeap(), 0, This->notifies);
118            This->notifies = NULL;
119            This->nrofnotifies = 0;
120         }
121 
122         return S_OK;
123 }
124 
125 static const IDirectSoundNotifyVtbl dsnvt =
126 {
127     IDirectSoundNotifyImpl_QueryInterface,
128     IDirectSoundNotifyImpl_AddRef,
129     IDirectSoundNotifyImpl_Release,
130     IDirectSoundNotifyImpl_SetNotificationPositions,
131 };
132 
133 /*******************************************************************************
134  *              IDirectSoundBuffer
135  */
136 
137 static inline IDirectSoundBufferImpl *impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8 *iface)
138 {
139     return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IDirectSoundBuffer8_iface);
140 }
141 
142 static inline BOOL is_primary_buffer(IDirectSoundBufferImpl *This)
143 {
144     return This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER ? TRUE : FALSE;
145 }
146 
147 static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(IDirectSoundBuffer8 *iface,
148         LPCWAVEFORMATEX wfex)
149 {
150     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
151 
152     TRACE("(%p,%p)\n", iface, wfex);
153 
154     if (is_primary_buffer(This))
155         return primarybuffer_SetFormat(This->device, wfex);
156     else {
157         WARN("not available for secondary buffers.\n");
158         return DSERR_INVALIDCALL;
159     }
160 }
161 
162 static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(IDirectSoundBuffer8 *iface, LONG vol)
163 {
164         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
165         LONG oldVol;
166 
167         HRESULT hres = DS_OK;
168 
169         TRACE("(%p,%d)\n",This,vol);
170 
171         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
172                 WARN("control unavailable: This->dsbd.dwFlags = 0x%08x\n", This->dsbd.dwFlags);
173                 return DSERR_CONTROLUNAVAIL;
174         }
175 
176         if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) {
177                 WARN("invalid parameter: vol = %d\n", vol);
178                 return DSERR_INVALIDPARAM;
179         }
180 
181         /* **** */
182         RtlAcquireResourceExclusive(&This->lock, TRUE);
183 
184         if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) {
185                 oldVol = This->ds3db_lVolume;
186                 This->ds3db_lVolume = vol;
187                 if (vol != oldVol)
188                         /* recalc 3d volume, which in turn recalcs the pans */
189                         DSOUND_Calc3DBuffer(This);
190         } else {
191                 oldVol = This->volpan.lVolume;
192                 This->volpan.lVolume = vol;
193                 if (vol != oldVol)
194                         DSOUND_RecalcVolPan(&(This->volpan));
195         }
196 
197         RtlReleaseResource(&This->lock);
198         /* **** */
199 
200         return hres;
201 }
202 
203 static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(IDirectSoundBuffer8 *iface, LONG *vol)
204 {
205         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
206 
207         TRACE("(%p,%p)\n",This,vol);
208 
209         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
210                 WARN("control unavailable\n");
211                 return DSERR_CONTROLUNAVAIL;
212         }
213 
214         if (vol == NULL) {
215                 WARN("invalid parameter: vol == NULL\n");
216                 return DSERR_INVALIDPARAM;
217         }
218 
219         *vol = This->volpan.lVolume;
220 
221         return DS_OK;
222 }
223 
224 static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(IDirectSoundBuffer8 *iface, DWORD freq)
225 {
226         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
227         DWORD oldFreq;
228 
229         TRACE("(%p,%d)\n",This,freq);
230 
231         if (is_primary_buffer(This)) {
232                 WARN("not available for primary buffers.\n");
233                 return DSERR_CONTROLUNAVAIL;
234         }
235 
236         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
237                 WARN("control unavailable\n");
238                 return DSERR_CONTROLUNAVAIL;
239         }
240 
241         if (freq == DSBFREQUENCY_ORIGINAL)
242                 freq = This->pwfx->nSamplesPerSec;
243 
244         if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) {
245                 WARN("invalid parameter: freq = %d\n", freq);
246                 return DSERR_INVALIDPARAM;
247         }
248 
249         /* **** */
250         RtlAcquireResourceExclusive(&This->lock, TRUE);
251 
252         oldFreq = This->freq;
253         This->freq = freq;
254         if (freq != oldFreq) {
255                 This->freqAdjust = This->freq / (float)This->device->pwfx->nSamplesPerSec;
256                 This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
257                 DSOUND_RecalcFormat(This);
258         }
259 
260         RtlReleaseResource(&This->lock);
261         /* **** */
262 
263         return DS_OK;
264 }
265 
266 static HRESULT WINAPI IDirectSoundBufferImpl_Play(IDirectSoundBuffer8 *iface, DWORD reserved1,
267         DWORD reserved2, DWORD flags)
268 {
269         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
270         HRESULT hres = DS_OK;
271 
272         TRACE("(%p,%08x,%08x,%08x)\n",This,reserved1,reserved2,flags);
273 
274         /* **** */
275         RtlAcquireResourceExclusive(&This->lock, TRUE);
276 
277         This->playflags = flags;
278         if (This->state == STATE_STOPPED) {
279                 This->leadin = TRUE;
280                 This->state = STATE_STARTING;
281         } else if (This->state == STATE_STOPPING)
282                 This->state = STATE_PLAYING;
283 
284         RtlReleaseResource(&This->lock);
285         /* **** */
286 
287         return hres;
288 }
289 
290 static HRESULT WINAPI IDirectSoundBufferImpl_Stop(IDirectSoundBuffer8 *iface)
291 {
292         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
293         HRESULT hres = DS_OK;
294 
295         TRACE("(%p)\n",This);
296 
297         /* **** */
298         RtlAcquireResourceExclusive(&This->lock, TRUE);
299 
300         if (This->state == STATE_PLAYING)
301                 This->state = STATE_STOPPING;
302         else if (This->state == STATE_STARTING)
303         {
304                 This->state = STATE_STOPPED;
305                 DSOUND_CheckEvent(This, 0, 0);
306         }
307 
308         RtlReleaseResource(&This->lock);
309         /* **** */
310 
311         return hres;
312 }
313 
314 static ULONG WINAPI IDirectSoundBufferImpl_AddRef(IDirectSoundBuffer8 *iface)
315 {
316     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
317     ULONG ref = InterlockedIncrement(&This->ref);
318 
319     TRACE("(%p) ref was %d\n", This, ref - 1);
320 
321     if(ref == 1)
322         InterlockedIncrement(&This->numIfaces);
323 
324     return ref;
325 }
326 
327 static ULONG WINAPI IDirectSoundBufferImpl_Release(IDirectSoundBuffer8 *iface)
328 {
329     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
330     ULONG ref;
331 
332     if (is_primary_buffer(This)){
333         ref = capped_refcount_dec(&This->ref);
334         if(!ref)
335             capped_refcount_dec(&This->numIfaces);
336         TRACE("(%p) ref is now: %d\n", This, ref);
337         return ref;
338     }
339 
340     ref = InterlockedDecrement(&This->ref);
341     if (!ref && !InterlockedDecrement(&This->numIfaces))
342             secondarybuffer_destroy(This);
343 
344     TRACE("(%p) ref is now %d\n", This, ref);
345 
346     return ref;
347 }
348 
349 static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(IDirectSoundBuffer8 *iface,
350         DWORD *playpos, DWORD *writepos)
351 {
352         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
353         DWORD pos;
354 
355         TRACE("(%p,%p,%p)\n",This,playpos,writepos);
356 
357         RtlAcquireResourceShared(&This->lock, TRUE);
358 
359         pos = This->sec_mixpos;
360 
361         /* sanity */
362         if (pos >= This->buflen){
363                 FIXME("Bad play position. playpos: %d, buflen: %d\n", pos, This->buflen);
364                 pos %= This->buflen;
365         }
366 
367         if (playpos)
368                 *playpos = pos;
369         if (writepos)
370                 *writepos = pos;
371 
372         if (writepos && This->state != STATE_STOPPED) {
373                 /* apply the documented 10ms lead to writepos */
374                 *writepos += This->writelead;
375                 *writepos %= This->buflen;
376         }
377 
378         RtlReleaseResource(&This->lock);
379 
380         TRACE("playpos = %d, writepos = %d, buflen=%d (%p, time=%d)\n",
381                 playpos?*playpos:-1, writepos?*writepos:-1, This->buflen, This, GetTickCount());
382 
383         return DS_OK;
384 }
385 
386 static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus(IDirectSoundBuffer8 *iface, DWORD *status)
387 {
388         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
389 
390         TRACE("(%p,%p), thread is %04x\n",This,status,GetCurrentThreadId());
391 
392         if (status == NULL) {
393                 WARN("invalid parameter: status = NULL\n");
394                 return DSERR_INVALIDPARAM;
395         }
396 
397         *status = 0;
398         RtlAcquireResourceShared(&This->lock, TRUE);
399         if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) {
400                 *status |= DSBSTATUS_PLAYING;
401                 if (This->playflags & DSBPLAY_LOOPING)
402                         *status |= DSBSTATUS_LOOPING;
403         }
404         RtlReleaseResource(&This->lock);
405 
406         TRACE("status=%x\n", *status);
407         return DS_OK;
408 }
409 
410 
411 static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat(IDirectSoundBuffer8 *iface,
412         LPWAVEFORMATEX lpwf, DWORD wfsize, DWORD *wfwritten)
413 {
414     IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
415     DWORD size;
416 
417     TRACE("(%p,%p,%d,%p)\n",This,lpwf,wfsize,wfwritten);
418 
419     size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
420 
421     if (lpwf) { /* NULL is valid */
422         if (wfsize >= size) {
423             CopyMemory(lpwf,This->pwfx,size);
424             if (wfwritten)
425                 *wfwritten = size;
426         } else {
427             WARN("invalid parameter: wfsize too small\n");
428             CopyMemory(lpwf,This->pwfx,wfsize);
429             if (wfwritten)
430                 *wfwritten = wfsize;
431             return DSERR_INVALIDPARAM;
432         }
433     } else {
434         if (wfwritten)
435             *wfwritten = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
436         else {
437             WARN("invalid parameter: wfwritten == NULL\n");
438             return DSERR_INVALIDPARAM;
439         }
440     }
441 
442     return DS_OK;
443 }
444 
445 static HRESULT WINAPI IDirectSoundBufferImpl_Lock(IDirectSoundBuffer8 *iface, DWORD writecursor,
446         DWORD writebytes, void **lplpaudioptr1, DWORD *audiobytes1, void **lplpaudioptr2,
447         DWORD *audiobytes2, DWORD flags)
448 {
449         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
450         HRESULT hres = DS_OK;
451 
452         TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n", This, writecursor, writebytes, lplpaudioptr1,
453                 audiobytes1, lplpaudioptr2, audiobytes2, flags, GetTickCount());
454 
455         if (!audiobytes1)
456             return DSERR_INVALIDPARAM;
457 
458         /* when this flag is set, writecursor is meaningless and must be calculated */
459         if (flags & DSBLOCK_FROMWRITECURSOR) {
460                 /* GetCurrentPosition does too much magic to duplicate here */
461                 hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writecursor);
462                 if (hres != DS_OK) {
463                         WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n");
464                         return hres;
465                 }
466         }
467 
468         /* when this flag is set, writebytes is meaningless and must be set */
469         if (flags & DSBLOCK_ENTIREBUFFER)
470                 writebytes = This->buflen;
471 
472         if (writecursor >= This->buflen) {
473                 WARN("Invalid parameter, writecursor: %u >= buflen: %u\n",
474                      writecursor, This->buflen);
475                 return DSERR_INVALIDPARAM;
476         }
477 
478         if (writebytes > This->buflen) {
479                 WARN("Invalid parameter, writebytes: %u > buflen: %u\n",
480                      writebytes, This->buflen);
481                 return DSERR_INVALIDPARAM;
482         }
483 
484         /* **** */
485         RtlAcquireResourceShared(&This->lock, TRUE);
486 
487         if (writecursor+writebytes <= This->buflen) {
488                 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
489                 if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
490                         WARN("Overwriting mixing position, case 1\n");
491                 *audiobytes1 = writebytes;
492                 if (lplpaudioptr2)
493                         *(LPBYTE*)lplpaudioptr2 = NULL;
494                 if (audiobytes2)
495                         *audiobytes2 = 0;
496                 TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n",
497                   *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
498                 TRACE("->%d.0\n",writebytes);
499         } else {
500                 DWORD remainder = writebytes + writecursor - This->buflen;
501                 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
502                 *audiobytes1 = This->buflen-writecursor;
503                 if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
504                         WARN("Overwriting mixing position, case 2\n");
505                 if (lplpaudioptr2)
506                         *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
507                 if (audiobytes2)
508                         *audiobytes2 = writebytes-(This->buflen-writecursor);
509                 if (audiobytes2 && This->sec_mixpos < remainder && This->state == STATE_PLAYING)
510                         WARN("Overwriting mixing position, case 3\n");
511                 TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
512         }
513 
514         RtlReleaseResource(&This->lock);
515         /* **** */
516 
517         return DS_OK;
518 }
519 
520 static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(IDirectSoundBuffer8 *iface,
521         DWORD newpos)
522 {
523         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
524         HRESULT hres = DS_OK;
525 
526         TRACE("(%p,%d)\n",This,newpos);
527 
528         /* **** */
529         RtlAcquireResourceExclusive(&This->lock, TRUE);
530 
531         /* start mixing from this new location instead */
532         newpos %= This->buflen;
533         newpos -= newpos%This->pwfx->nBlockAlign;
534         This->sec_mixpos = newpos;
535 
536         /* at this point, do not attempt to reset buffers, mess with primary mix position,
537            or anything like that to reduce latency. The data already prebuffered cannot be changed */
538 
539         RtlReleaseResource(&This->lock);
540         /* **** */
541 
542         return hres;
543 }
544 
545 static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(IDirectSoundBuffer8 *iface, LONG pan)
546 {
547         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
548         HRESULT hres = DS_OK;
549 
550         TRACE("(%p,%d)\n",This,pan);
551 
552         if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) {
553                 WARN("invalid parameter: pan = %d\n", pan);
554                 return DSERR_INVALIDPARAM;
555         }
556 
557         /* You cannot use both pan and 3D controls */
558         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
559             (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) {
560                 WARN("control unavailable\n");
561                 return DSERR_CONTROLUNAVAIL;
562         }
563 
564         /* **** */
565         RtlAcquireResourceExclusive(&This->lock, TRUE);
566 
567         if (This->volpan.lPan != pan) {
568                 This->volpan.lPan = pan;
569                 DSOUND_RecalcVolPan(&(This->volpan));
570         }
571 
572         RtlReleaseResource(&This->lock);
573         /* **** */
574 
575         return hres;
576 }
577 
578 static HRESULT WINAPI IDirectSoundBufferImpl_GetPan(IDirectSoundBuffer8 *iface, LONG *pan)
579 {
580         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
581 
582         TRACE("(%p,%p)\n",This,pan);
583 
584         if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
585                 WARN("control unavailable\n");
586                 return DSERR_CONTROLUNAVAIL;
587         }
588 
589         if (pan == NULL) {
590                 WARN("invalid parameter: pan = NULL\n");
591                 return DSERR_INVALIDPARAM;
592         }
593 
594         *pan = This->volpan.lPan;
595 
596         return DS_OK;
597 }
598 
599 static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(IDirectSoundBuffer8 *iface, void *p1, DWORD x1,
600         void *p2, DWORD x2)
601 {
602         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface), *iter;
603         HRESULT hres = DS_OK;
604 
605         TRACE("(%p,%p,%d,%p,%d)\n", This,p1,x1,p2,x2);
606 
607         if (!p2)
608                 x2 = 0;
609 
610     if((p1 && ((BYTE*)p1 < This->buffer->memory ||
611                     (BYTE*)p1 >= This->buffer->memory + This->buflen)) ||
612             (p2 && ((BYTE*)p2 < This->buffer->memory ||
613                     (BYTE*)p2 >= This->buffer->memory + This->buflen)))
614         return DSERR_INVALIDPARAM;
615 
616         if (x1 || x2)
617         {
618                 RtlAcquireResourceShared(&This->device->buffer_list_lock, TRUE);
619                 LIST_FOR_EACH_ENTRY(iter, &This->buffer->buffers, IDirectSoundBufferImpl, entry )
620                 {
621                         RtlAcquireResourceShared(&iter->lock, TRUE);
622                         if (x1)
623                         {
624                             if(x1 + (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory > iter->buflen)
625                               hres = DSERR_INVALIDPARAM;
626                         }
627                         RtlReleaseResource(&iter->lock);
628                 }
629                 RtlReleaseResource(&This->device->buffer_list_lock);
630         }
631 
632         return hres;
633 }
634 
635 static HRESULT WINAPI IDirectSoundBufferImpl_Restore(IDirectSoundBuffer8 *iface)
636 {
637         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
638 
639         FIXME("(%p):stub\n",This);
640         return DS_OK;
641 }
642 
643 static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(IDirectSoundBuffer8 *iface, DWORD *freq)
644 {
645         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
646 
647         TRACE("(%p,%p)\n",This,freq);
648 
649         if (freq == NULL) {
650                 WARN("invalid parameter: freq = NULL\n");
651                 return DSERR_INVALIDPARAM;
652         }
653 
654         *freq = This->freq;
655         TRACE("-> %d\n", *freq);
656 
657         return DS_OK;
658 }
659 
660 static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(IDirectSoundBuffer8 *iface, DWORD dwEffectsCount,
661         LPDSEFFECTDESC pDSFXDesc, DWORD *pdwResultCodes)
662 {
663         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
664         DWORD u;
665 
666         FIXME("(%p,%u,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
667 
668         if (pdwResultCodes)
669                 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
670 
671         WARN("control unavailable\n");
672         return DSERR_CONTROLUNAVAIL;
673 }
674 
675 static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(IDirectSoundBuffer8 *iface,
676         DWORD dwFlags, DWORD dwEffectsCount, DWORD *pdwResultCodes)
677 {
678         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
679         DWORD u;
680 
681         FIXME("(%p,%08u,%u,%p): stub, faking success\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
682 
683         if (pdwResultCodes)
684                 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
685 
686         WARN("control unavailable\n");
687         return DS_OK;
688 }
689 
690 static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(IDirectSoundBuffer8 *iface,
691         REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, void **ppObject)
692 {
693         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
694 
695         FIXME("(%p,%s,%u,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
696 
697         WARN("control unavailable\n");
698         return DSERR_CONTROLUNAVAIL;
699 }
700 
701 static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(IDirectSoundBuffer8 *iface,
702         IDirectSound *dsound, LPCDSBUFFERDESC dbsd)
703 {
704         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
705 
706         WARN("(%p) already initialized\n", This);
707         return DSERR_ALREADYINITIALIZED;
708 }
709 
710 static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(IDirectSoundBuffer8 *iface, LPDSBCAPS caps)
711 {
712         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
713 
714         TRACE("(%p)->(%p)\n",This,caps);
715 
716         if (caps == NULL) {
717                 WARN("invalid parameter: caps == NULL\n");
718                 return DSERR_INVALIDPARAM;
719         }
720 
721         if (caps->dwSize < sizeof(*caps)) {
722                 WARN("invalid parameter: caps->dwSize = %d\n",caps->dwSize);
723                 return DSERR_INVALIDPARAM;
724         }
725 
726         caps->dwFlags = This->dsbd.dwFlags;
727         caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
728 
729         caps->dwBufferBytes = This->buflen;
730 
731         /* According to windows, this is zero*/
732         caps->dwUnlockTransferRate = 0;
733         caps->dwPlayCpuOverhead = 0;
734 
735         return DS_OK;
736 }
737 
738 static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(IDirectSoundBuffer8 *iface, REFIID riid,
739         void **ppobj)
740 {
741         IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
742 
743         TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
744 
745         if (ppobj == NULL) {
746                 WARN("invalid parameter\n");
747                 return E_INVALIDARG;
748         }
749 
750         *ppobj = NULL;  /* assume failure */
751 
752         if ( IsEqualGUID(riid, &IID_IUnknown) ||
753              IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
754              IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
755                 IDirectSoundBuffer8_AddRef(iface);
756                 *ppobj = iface;
757                 return S_OK;
758         }
759 
760         if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
761                 IDirectSoundNotify_AddRef(&This->IDirectSoundNotify_iface);
762                 *ppobj = &This->IDirectSoundNotify_iface;
763                 return S_OK;
764         }
765 
766         if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
767                 IDirectSound3DBuffer_AddRef(&This->IDirectSound3DBuffer_iface);
768                 *ppobj = &This->IDirectSound3DBuffer_iface;
769                 return S_OK;
770         }
771 
772         if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
773                 ERR("app requested IDirectSound3DListener on secondary buffer\n");
774                 return E_NOINTERFACE;
775         }
776 
777         if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
778                 IKsPropertySet_AddRef(&This->IKsPropertySet_iface);
779                 *ppobj = &This->IKsPropertySet_iface;
780                 return S_OK;
781         }
782 
783         FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
784 
785         return E_NOINTERFACE;
786 }
787 
788 static const IDirectSoundBuffer8Vtbl dsbvt =
789 {
790         IDirectSoundBufferImpl_QueryInterface,
791         IDirectSoundBufferImpl_AddRef,
792         IDirectSoundBufferImpl_Release,
793         IDirectSoundBufferImpl_GetCaps,
794         IDirectSoundBufferImpl_GetCurrentPosition,
795         IDirectSoundBufferImpl_GetFormat,
796         IDirectSoundBufferImpl_GetVolume,
797         IDirectSoundBufferImpl_GetPan,
798         IDirectSoundBufferImpl_GetFrequency,
799         IDirectSoundBufferImpl_GetStatus,
800         IDirectSoundBufferImpl_Initialize,
801         IDirectSoundBufferImpl_Lock,
802         IDirectSoundBufferImpl_Play,
803         IDirectSoundBufferImpl_SetCurrentPosition,
804         IDirectSoundBufferImpl_SetFormat,
805         IDirectSoundBufferImpl_SetVolume,
806         IDirectSoundBufferImpl_SetPan,
807         IDirectSoundBufferImpl_SetFrequency,
808         IDirectSoundBufferImpl_Stop,
809         IDirectSoundBufferImpl_Unlock,
810         IDirectSoundBufferImpl_Restore,
811         IDirectSoundBufferImpl_SetFX,
812         IDirectSoundBufferImpl_AcquireResources,
813         IDirectSoundBufferImpl_GetObjectInPath
814 };
815 
816 HRESULT IDirectSoundBufferImpl_Create(
817         DirectSoundDevice * device,
818         IDirectSoundBufferImpl **pdsb,
819         LPCDSBUFFERDESC dsbd)
820 {
821         IDirectSoundBufferImpl *dsb;
822         LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
823         HRESULT err = DS_OK;
824         DWORD capf = 0;
825         TRACE("(%p,%p,%p)\n",device,pdsb,dsbd);
826 
827         if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
828                 WARN("invalid parameter: dsbd->dwBufferBytes = %d\n", dsbd->dwBufferBytes);
829                 *pdsb = NULL;
830                 return DSERR_INVALIDPARAM; /* FIXME: which error? */
831         }
832 
833         dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
834 
835         if (dsb == 0) {
836                 WARN("out of memory\n");
837                 *pdsb = NULL;
838                 return DSERR_OUTOFMEMORY;
839         }
840 
841         TRACE("Created buffer at %p\n", dsb);
842 
843         dsb->ref = 0;
844         dsb->refn = 0;
845         dsb->ref3D = 0;
846         dsb->refiks = 0;
847         dsb->numIfaces = 0;
848         dsb->device = device;
849         dsb->IDirectSoundBuffer8_iface.lpVtbl = &dsbvt;
850         dsb->IDirectSoundNotify_iface.lpVtbl = &dsnvt;
851         dsb->IDirectSound3DBuffer_iface.lpVtbl = &ds3dbvt;
852         dsb->IKsPropertySet_iface.lpVtbl = &iksbvt;
853 
854         /* size depends on version */
855         CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize);
856 
857         dsb->pwfx = DSOUND_CopyFormat(wfex);
858         if (dsb->pwfx == NULL) {
859                 HeapFree(GetProcessHeap(),0,dsb);
860                 *pdsb = NULL;
861                 return DSERR_OUTOFMEMORY;
862         }
863 
864         if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign)
865                 dsb->buflen = dsbd->dwBufferBytes + 
866                         (dsbd->lpwfxFormat->nBlockAlign - 
867                         (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign));
868         else
869                 dsb->buflen = dsbd->dwBufferBytes;
870 
871         dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
872         dsb->notifies = NULL;
873         dsb->nrofnotifies = 0;
874 
875         /* Check necessary hardware mixing capabilities */
876         if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
877         else capf |= DSCAPS_SECONDARYMONO;
878         if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
879         else capf |= DSCAPS_SECONDARY8BIT;
880 
881         TRACE("capf = 0x%08x, device->drvcaps.dwFlags = 0x%08x\n", capf, device->drvcaps.dwFlags);
882 
883         /* Allocate an empty buffer */
884         dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
885         if (dsb->buffer == NULL) {
886                 WARN("out of memory\n");
887                 HeapFree(GetProcessHeap(),0,dsb->pwfx);
888                 HeapFree(GetProcessHeap(),0,dsb);
889                 *pdsb = NULL;
890                 return DSERR_OUTOFMEMORY;
891         }
892 
893         /* Allocate system memory for buffer */
894         dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
895         if (dsb->buffer->memory == NULL) {
896                 WARN("out of memory\n");
897                 HeapFree(GetProcessHeap(),0,dsb->pwfx);
898                 HeapFree(GetProcessHeap(),0,dsb->buffer);
899                 HeapFree(GetProcessHeap(),0,dsb);
900                 *pdsb = NULL;
901                 return DSERR_OUTOFMEMORY;
902         }
903 
904         dsb->buffer->ref = 1;
905         list_init(&dsb->buffer->buffers);
906         list_add_head(&dsb->buffer->buffers, &dsb->entry);
907         FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0);
908 
909         /* It's not necessary to initialize values to zero since */
910         /* we allocated this structure with HEAP_ZERO_MEMORY... */
911         dsb->sec_mixpos = 0;
912         dsb->state = STATE_STOPPED;
913 
914         dsb->freqAdjust = dsb->freq / (float)device->pwfx->nSamplesPerSec;
915         dsb->nAvgBytesPerSec = dsb->freq *
916                 dsbd->lpwfxFormat->nBlockAlign;
917 
918         /* calculate fragment size and write lead */
919         DSOUND_RecalcFormat(dsb);
920 
921         if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
922                 dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
923                 dsb->ds3db_ds3db.vPosition.x = 0.0;
924                 dsb->ds3db_ds3db.vPosition.y = 0.0;
925                 dsb->ds3db_ds3db.vPosition.z = 0.0;
926                 dsb->ds3db_ds3db.vVelocity.x = 0.0;
927                 dsb->ds3db_ds3db.vVelocity.y = 0.0;
928                 dsb->ds3db_ds3db.vVelocity.z = 0.0;
929                 dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
930                 dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
931                 dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
932                 dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
933                 dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
934                 dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
935                 dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
936                 dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
937                 dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
938 
939                 dsb->ds3db_need_recalc = FALSE;
940                 DSOUND_Calc3DBuffer(dsb);
941         } else
942                 DSOUND_RecalcVolPan(&(dsb->volpan));
943 
944         RtlInitializeResource(&dsb->lock);
945 
946         /* register buffer if not primary */
947         if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
948                 err = DirectSoundDevice_AddBuffer(device, dsb);
949                 if (err != DS_OK) {
950                         HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
951                         HeapFree(GetProcessHeap(),0,dsb->buffer);
952                         RtlDeleteResource(&dsb->lock);
953                         HeapFree(GetProcessHeap(),0,dsb->pwfx);
954                         HeapFree(GetProcessHeap(),0,dsb);
955                         dsb = NULL;
956                 }
957         }
958 
959         IDirectSoundBuffer8_AddRef(&dsb->IDirectSoundBuffer8_iface);
960         *pdsb = dsb;
961         return err;
962 }
963 
964 void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
965 {
966     ULONG ref = InterlockedIncrement(&This->numIfaces);
967 
968     if (ref > 1)
969         WARN("Destroying buffer with %u in use interfaces\n", ref - 1);
970 
971     DirectSoundDevice_RemoveBuffer(This->device, This);
972     RtlDeleteResource(&This->lock);
973 
974     This->buffer->ref--;
975     list_remove(&This->entry);
976     if (This->buffer->ref == 0) {
977         HeapFree(GetProcessHeap(), 0, This->buffer->memory);
978         HeapFree(GetProcessHeap(), 0, This->buffer);
979     }
980 
981     HeapFree(GetProcessHeap(), 0, This->notifies);
982     HeapFree(GetProcessHeap(), 0, This->pwfx);
983     HeapFree(GetProcessHeap(), 0, This);
984 
985     TRACE("(%p) released\n", This);
986 }
987 
988 HRESULT IDirectSoundBufferImpl_Duplicate(
989     DirectSoundDevice *device,
990     IDirectSoundBufferImpl **ppdsb,
991     IDirectSoundBufferImpl *pdsb)
992 {
993     IDirectSoundBufferImpl *dsb;
994     HRESULT hres = DS_OK;
995     TRACE("(%p,%p,%p)\n", device, ppdsb, pdsb);
996 
997     dsb = HeapAlloc(GetProcessHeap(),0,sizeof(*dsb));
998     if (dsb == NULL) {
999         WARN("out of memory\n");
1000         *ppdsb = NULL;
1001         return DSERR_OUTOFMEMORY;
1002     }
1003 
1004     RtlAcquireResourceShared(&pdsb->lock, TRUE);
1005 
1006     CopyMemory(dsb, pdsb, sizeof(*dsb));
1007 
1008     dsb->pwfx = DSOUND_CopyFormat(pdsb->pwfx);
1009 
1010     RtlReleaseResource(&pdsb->lock);
1011 
1012     if (dsb->pwfx == NULL) {
1013         HeapFree(GetProcessHeap(),0,dsb);
1014         *ppdsb = NULL;
1015         return DSERR_OUTOFMEMORY;
1016     }
1017 
1018     dsb->buffer->ref++;
1019     list_add_head(&dsb->buffer->buffers, &dsb->entry);
1020     dsb->ref = 0;
1021     dsb->refn = 0;
1022     dsb->ref3D = 0;
1023     dsb->refiks = 0;
1024     dsb->numIfaces = 0;
1025     dsb->state = STATE_STOPPED;
1026     dsb->sec_mixpos = 0;
1027     dsb->notifies = NULL;
1028     dsb->nrofnotifies = 0;
1029     dsb->device = device;
1030     DSOUND_RecalcFormat(dsb);
1031 
1032     RtlInitializeResource(&dsb->lock);
1033 
1034     /* register buffer */
1035     hres = DirectSoundDevice_AddBuffer(device, dsb);
1036     if (hres != DS_OK) {
1037         RtlDeleteResource(&dsb->lock);
1038         list_remove(&dsb->entry);
1039         dsb->buffer->ref--;
1040         HeapFree(GetProcessHeap(),0,dsb->pwfx);
1041         HeapFree(GetProcessHeap(),0,dsb);
1042         dsb = NULL;
1043     }
1044 
1045     IDirectSoundBuffer8_AddRef(&dsb->IDirectSoundBuffer8_iface);
1046     *ppdsb = dsb;
1047     return hres;
1048 }
1049 
1050 /*******************************************************************************
1051  *              IKsPropertySet
1052  */
1053 
1054 static inline IDirectSoundBufferImpl *impl_from_IKsPropertySet(IKsPropertySet *iface)
1055 {
1056     return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IKsPropertySet_iface);
1057 }
1058 
1059 /* IUnknown methods */
1060 static HRESULT WINAPI IKsPropertySetImpl_QueryInterface(IKsPropertySet *iface, REFIID riid,
1061         void **ppobj)
1062 {
1063     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1064 
1065     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1066 
1067     return IDirectSoundBuffer_QueryInterface(&This->IDirectSoundBuffer8_iface, riid, ppobj);
1068 }
1069 
1070 static ULONG WINAPI IKsPropertySetImpl_AddRef(IKsPropertySet *iface)
1071 {
1072     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1073     ULONG ref = InterlockedIncrement(&This->refiks);
1074 
1075     TRACE("(%p) ref was %d\n", This, ref - 1);
1076 
1077     if(ref == 1)
1078         InterlockedIncrement(&This->numIfaces);
1079 
1080     return ref;
1081 }
1082 
1083 static ULONG WINAPI IKsPropertySetImpl_Release(IKsPropertySet *iface)
1084 {
1085     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1086     ULONG ref;
1087 
1088     if (is_primary_buffer(This)){
1089         ref = capped_refcount_dec(&This->refiks);
1090         if(!ref)
1091             capped_refcount_dec(&This->numIfaces);
1092         TRACE("(%p) ref is now: %d\n", This, ref);
1093         return ref;
1094     }
1095 
1096     ref = InterlockedDecrement(&This->refiks);
1097     if (!ref && !InterlockedDecrement(&This->numIfaces))
1098         secondarybuffer_destroy(This);
1099 
1100     TRACE("(%p) ref is now %d\n", This, ref);
1101 
1102     return ref;
1103 }
1104 
1105 static HRESULT WINAPI IKsPropertySetImpl_Get(IKsPropertySet *iface, REFGUID guidPropSet,
1106         ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
1107         ULONG cbPropData, ULONG *pcbReturned)
1108 {
1109     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1110 
1111     TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
1112     This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1113 
1114     return E_PROP_ID_UNSUPPORTED;
1115 }
1116 
1117 static HRESULT WINAPI IKsPropertySetImpl_Set(IKsPropertySet *iface, REFGUID guidPropSet,
1118         ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
1119         ULONG cbPropData)
1120 {
1121     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1122 
1123     TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1124 
1125     return E_PROP_ID_UNSUPPORTED;
1126 }
1127 
1128 static HRESULT WINAPI IKsPropertySetImpl_QuerySupport(IKsPropertySet *iface, REFGUID guidPropSet,
1129         ULONG dwPropID, ULONG *pTypeSupport)
1130 {
1131     IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface);
1132 
1133     TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1134 
1135     return E_PROP_ID_UNSUPPORTED;
1136 }
1137 
1138 const IKsPropertySetVtbl iksbvt = {
1139     IKsPropertySetImpl_QueryInterface,
1140     IKsPropertySetImpl_AddRef,
1141     IKsPropertySetImpl_Release,
1142     IKsPropertySetImpl_Get,
1143     IKsPropertySetImpl_Set,
1144     IKsPropertySetImpl_QuerySupport
1145 };
1146 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.