ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

buffer.c
Go to the documentation of this file.
00001 /*              DirectSound
00002  *
00003  * Copyright 1998 Marcus Meissner
00004  * Copyright 1998 Rob Riggs
00005  * Copyright 2000-2002 TransGaming Technologies, Inc.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include <stdarg.h>
00023 
00024 #define NONAMELESSSTRUCT
00025 #define NONAMELESSUNION
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winuser.h"
00029 #include "mmsystem.h"
00030 #include "winternl.h"
00031 #include "wine/debug.h"
00032 #include "dsound.h"
00033 #include "dsdriver.h"
00034 #include "dsound_private.h"
00035 
00036 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
00037 
00038 static HRESULT SecondaryBufferImpl_Destroy(SecondaryBufferImpl *pdsb);
00039 
00040 /*******************************************************************************
00041  *      IDirectSoundNotify
00042  */
00043 
00044 struct IDirectSoundNotifyImpl
00045 {
00046     /* IUnknown fields */
00047     const IDirectSoundNotifyVtbl *lpVtbl;
00048     LONG                        ref;
00049     IDirectSoundBufferImpl*     dsb;
00050 };
00051 
00052 static HRESULT IDirectSoundNotifyImpl_Create(IDirectSoundBufferImpl *dsb,
00053                                              IDirectSoundNotifyImpl **pdsn);
00054 static HRESULT IDirectSoundNotifyImpl_Destroy(IDirectSoundNotifyImpl *pdsn);
00055 
00056 static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
00057     LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj
00058 ) {
00059     IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
00060     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00061 
00062     if (This->dsb == NULL) {
00063         WARN("invalid parameter\n");
00064         return E_INVALIDARG;
00065     }
00066 
00067     return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER)This->dsb, riid, ppobj);
00068 }
00069 
00070 static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
00071 {
00072     IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
00073     ULONG ref = InterlockedIncrement(&(This->ref));
00074     TRACE("(%p) ref was %d\n", This, ref - 1);
00075     return ref;
00076 }
00077 
00078 static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
00079 {
00080     IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
00081     ULONG ref = InterlockedDecrement(&(This->ref));
00082     TRACE("(%p) ref was %d\n", This, ref + 1);
00083 
00084     if (!ref) {
00085         IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb);
00086         This->dsb->notify = NULL;
00087         HeapFree(GetProcessHeap(), 0, This);
00088         TRACE("(%p) released\n", This);
00089     }
00090     return ref;
00091 }
00092 
00093 static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
00094     LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
00095 ) {
00096     IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
00097     TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
00098 
00099         if (howmuch > 0 && notify == NULL) {
00100         WARN("invalid parameter: notify == NULL\n");
00101         return DSERR_INVALIDPARAM;
00102     }
00103 
00104     if (TRACE_ON(dsound)) {
00105         unsigned int    i;
00106         for (i=0;i<howmuch;i++)
00107         TRACE("notify at %d to %p\n",
00108             notify[i].dwOffset,notify[i].hEventNotify);
00109     }
00110 
00111     if (This->dsb->hwnotify) {
00112         HRESULT hres;
00113         hres = IDsDriverNotify_SetNotificationPositions(This->dsb->hwnotify, howmuch, notify);
00114         if (hres != DS_OK)
00115             WARN("IDsDriverNotify_SetNotificationPositions failed\n");
00116         return hres;
00117         } else if (howmuch > 0) {
00118         /* Make an internal copy of the caller-supplied array.
00119          * Replace the existing copy if one is already present. */
00120         HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
00121         This->dsb->notifies = HeapAlloc(GetProcessHeap(), 0,
00122             howmuch * sizeof(DSBPOSITIONNOTIFY));
00123 
00124         if (This->dsb->notifies == NULL) {
00125             WARN("out of memory\n");
00126             return DSERR_OUTOFMEMORY;
00127         }
00128         CopyMemory(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
00129         This->dsb->nrofnotifies = howmuch;
00130         } else {
00131            HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
00132            This->dsb->notifies = NULL;
00133            This->dsb->nrofnotifies = 0;
00134         }
00135 
00136     return S_OK;
00137 }
00138 
00139 static const IDirectSoundNotifyVtbl dsnvt =
00140 {
00141     IDirectSoundNotifyImpl_QueryInterface,
00142     IDirectSoundNotifyImpl_AddRef,
00143     IDirectSoundNotifyImpl_Release,
00144     IDirectSoundNotifyImpl_SetNotificationPositions,
00145 };
00146 
00147 static HRESULT IDirectSoundNotifyImpl_Create(
00148     IDirectSoundBufferImpl * dsb,
00149     IDirectSoundNotifyImpl **pdsn)
00150 {
00151     IDirectSoundNotifyImpl * dsn;
00152     TRACE("(%p,%p)\n",dsb,pdsn);
00153 
00154     dsn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dsn));
00155 
00156     if (dsn == NULL) {
00157         WARN("out of memory\n");
00158         return DSERR_OUTOFMEMORY;
00159     }
00160 
00161     dsn->ref = 0;
00162     dsn->lpVtbl = &dsnvt;
00163     dsn->dsb = dsb;
00164     dsb->notify = dsn;
00165     IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
00166 
00167     *pdsn = dsn;
00168     return DS_OK;
00169 }
00170 
00171 static HRESULT IDirectSoundNotifyImpl_Destroy(
00172     IDirectSoundNotifyImpl *pdsn)
00173 {
00174     TRACE("(%p)\n",pdsn);
00175 
00176     while (IDirectSoundNotifyImpl_Release((LPDIRECTSOUNDNOTIFY)pdsn) > 0);
00177 
00178     return DS_OK;
00179 }
00180 
00181 /*******************************************************************************
00182  *      IDirectSoundBuffer
00183  */
00184 
00185 static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(
00186     LPDIRECTSOUNDBUFFER8 iface,LPCWAVEFORMATEX wfex
00187 ) {
00188     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00189 
00190     TRACE("(%p,%p)\n",This,wfex);
00191     /* This method is not available on secondary buffers */
00192     WARN("invalid call\n");
00193     return DSERR_INVALIDCALL;
00194 }
00195 
00196 static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(
00197     LPDIRECTSOUNDBUFFER8 iface,LONG vol
00198 ) {
00199     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00200     LONG oldVol;
00201     HRESULT hres = DS_OK;
00202 
00203     TRACE("(%p,%d)\n",This,vol);
00204 
00205     if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
00206         WARN("control unavailable: This->dsbd.dwFlags = 0x%08x\n", This->dsbd.dwFlags);
00207         return DSERR_CONTROLUNAVAIL;
00208     }
00209 
00210     if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) {
00211         WARN("invalid parameter: vol = %d\n", vol);
00212         return DSERR_INVALIDPARAM;
00213     }
00214 
00215     /* **** */
00216     RtlAcquireResourceExclusive(&This->lock, TRUE);
00217 
00218     if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) {
00219         oldVol = This->ds3db_lVolume;
00220         This->ds3db_lVolume = vol;
00221         if (vol != oldVol)
00222             /* recalc 3d volume, which in turn recalcs the pans */
00223             DSOUND_Calc3DBuffer(This);
00224     } else {
00225         oldVol = This->volpan.lVolume;
00226         This->volpan.lVolume = vol;
00227         if (vol != oldVol)
00228             DSOUND_RecalcVolPan(&(This->volpan));
00229     }
00230 
00231     if (vol != oldVol) {
00232         if (This->hwbuf) {
00233             hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
00234                 if (hres != DS_OK)
00235                     WARN("IDsDriverBuffer_SetVolumePan failed\n");
00236         }
00237     }
00238 
00239     RtlReleaseResource(&This->lock);
00240     /* **** */
00241 
00242     return hres;
00243 }
00244 
00245 static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(
00246     LPDIRECTSOUNDBUFFER8 iface,LPLONG vol
00247 ) {
00248     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00249     TRACE("(%p,%p)\n",This,vol);
00250 
00251     if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
00252         WARN("control unavailable\n");
00253         return DSERR_CONTROLUNAVAIL;
00254     }
00255 
00256     if (vol == NULL) {
00257         WARN("invalid parameter: vol == NULL\n");
00258         return DSERR_INVALIDPARAM;
00259     }
00260 
00261     *vol = This->volpan.lVolume;
00262 
00263     return DS_OK;
00264 }
00265 
00266 static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(
00267     LPDIRECTSOUNDBUFFER8 iface,DWORD freq
00268 ) {
00269     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00270     DWORD oldFreq;
00271 
00272     TRACE("(%p,%d)\n",This,freq);
00273 
00274     if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
00275         WARN("control unavailable\n");
00276         return DSERR_CONTROLUNAVAIL;
00277     }
00278 
00279     if (freq == DSBFREQUENCY_ORIGINAL)
00280         freq = This->pwfx->nSamplesPerSec;
00281 
00282     if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) {
00283         WARN("invalid parameter: freq = %d\n", freq);
00284         return DSERR_INVALIDPARAM;
00285     }
00286 
00287     /* **** */
00288     RtlAcquireResourceExclusive(&This->lock, TRUE);
00289 
00290     oldFreq = This->freq;
00291     This->freq = freq;
00292     if (freq != oldFreq) {
00293         This->freqAdjust = ((DWORD64)This->freq << DSOUND_FREQSHIFT) / This->device->pwfx->nSamplesPerSec;
00294         This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
00295         DSOUND_RecalcFormat(This);
00296         DSOUND_MixToTemporary(This, 0, This->buflen, FALSE);
00297     }
00298 
00299     RtlReleaseResource(&This->lock);
00300     /* **** */
00301 
00302     return DS_OK;
00303 }
00304 
00305 static HRESULT WINAPI IDirectSoundBufferImpl_Play(
00306     LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags
00307 ) {
00308     HRESULT hres = DS_OK;
00309     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00310     TRACE("(%p,%08x,%08x,%08x)\n",This,reserved1,reserved2,flags);
00311 
00312     /* **** */
00313     RtlAcquireResourceExclusive(&This->lock, TRUE);
00314 
00315     This->playflags = flags;
00316     if (This->state == STATE_STOPPED && !This->hwbuf) {
00317         This->leadin = TRUE;
00318         This->state = STATE_STARTING;
00319     } else if (This->state == STATE_STOPPING)
00320         This->state = STATE_PLAYING;
00321     if (This->hwbuf) {
00322         hres = IDsDriverBuffer_Play(This->hwbuf, 0, 0, This->playflags);
00323         if (hres != DS_OK)
00324             WARN("IDsDriverBuffer_Play failed\n");
00325         else
00326             This->state = STATE_PLAYING;
00327     }
00328 
00329     RtlReleaseResource(&This->lock);
00330     /* **** */
00331 
00332     return hres;
00333 }
00334 
00335 static HRESULT WINAPI IDirectSoundBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface)
00336 {
00337     HRESULT hres = DS_OK;
00338     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00339     TRACE("(%p)\n",This);
00340 
00341     /* **** */
00342     RtlAcquireResourceExclusive(&This->lock, TRUE);
00343 
00344     if (This->state == STATE_PLAYING)
00345         This->state = STATE_STOPPING;
00346     else if (This->state == STATE_STARTING)
00347     {
00348         This->state = STATE_STOPPED;
00349         DSOUND_CheckEvent(This, 0, 0);
00350     }
00351     if (This->hwbuf) {
00352         hres = IDsDriverBuffer_Stop(This->hwbuf);
00353         if (hres != DS_OK)
00354             WARN("IDsDriverBuffer_Stop failed\n");
00355         else
00356             This->state = STATE_STOPPED;
00357     }
00358 
00359     RtlReleaseResource(&This->lock);
00360     /* **** */
00361 
00362     return hres;
00363 }
00364 
00365 static ULONG WINAPI IDirectSoundBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface)
00366 {
00367     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00368     ULONG ref = InterlockedIncrement(&(This->ref));
00369     TRACE("(%p) ref was %d\n", This, ref - 1);
00370     return ref;
00371 }
00372 
00373 static ULONG WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface)
00374 {
00375     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00376     ULONG ref = InterlockedDecrement(&(This->ref));
00377     TRACE("(%p) ref was %d\n", This, ref + 1);
00378 
00379     if (!ref) {
00380     DirectSoundDevice_RemoveBuffer(This->device, This);
00381     RtlDeleteResource(&This->lock);
00382 
00383     if (This->hwbuf)
00384         IDsDriverBuffer_Release(This->hwbuf);
00385     if (!This->hwbuf || (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)) {
00386         This->buffer->ref--;
00387         list_remove(&This->entry);
00388         if (This->buffer->ref==0) {
00389             HeapFree(GetProcessHeap(),0,This->buffer->memory);
00390             HeapFree(GetProcessHeap(),0,This->buffer);
00391         }
00392     }
00393 
00394     HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
00395     HeapFree(GetProcessHeap(), 0, This->notifies);
00396     HeapFree(GetProcessHeap(), 0, This->pwfx);
00397     HeapFree(GetProcessHeap(), 0, This);
00398 
00399     TRACE("(%p) released\n", This);
00400     }
00401     return ref;
00402 }
00403 
00404 static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(
00405     LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos
00406 ) {
00407     HRESULT hres;
00408     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00409     TRACE("(%p,%p,%p)\n",This,playpos,writepos);
00410 
00411     RtlAcquireResourceShared(&This->lock, TRUE);
00412     if (This->hwbuf) {
00413         hres=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos);
00414         if (hres != DS_OK) {
00415             WARN("IDsDriverBuffer_GetPosition failed\n");
00416             return hres;
00417         }
00418     } else {
00419         DWORD pos = This->sec_mixpos;
00420 
00421         /* sanity */
00422         if (pos >= This->buflen){
00423             FIXME("Bad play position. playpos: %d, buflen: %d\n", pos, This->buflen);
00424             pos %= This->buflen;
00425         }
00426 
00427         if (playpos)
00428             *playpos = pos;
00429         if (writepos)
00430             *writepos = pos;
00431     }
00432     if (writepos && This->state != STATE_STOPPED && (!This->hwbuf || !(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDWRITELEAD))) {
00433         /* apply the documented 10ms lead to writepos */
00434         *writepos += This->writelead;
00435         *writepos %= This->buflen;
00436     }
00437     RtlReleaseResource(&This->lock);
00438 
00439     TRACE("playpos = %d, writepos = %d, buflen=%d (%p, time=%d)\n",
00440         playpos?*playpos:-1, writepos?*writepos:-1, This->buflen, This, GetTickCount());
00441 
00442     return DS_OK;
00443 }
00444 
00445 static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus(
00446     LPDIRECTSOUNDBUFFER8 iface,LPDWORD status
00447 ) {
00448     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00449     TRACE("(%p,%p), thread is %04x\n",This,status,GetCurrentThreadId());
00450 
00451     if (status == NULL) {
00452         WARN("invalid parameter: status = NULL\n");
00453         return DSERR_INVALIDPARAM;
00454     }
00455 
00456     *status = 0;
00457     RtlAcquireResourceShared(&This->lock, TRUE);
00458     if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) {
00459         *status |= DSBSTATUS_PLAYING;
00460         if (This->playflags & DSBPLAY_LOOPING)
00461             *status |= DSBSTATUS_LOOPING;
00462     }
00463     RtlReleaseResource(&This->lock);
00464 
00465     TRACE("status=%x\n", *status);
00466     return DS_OK;
00467 }
00468 
00469 
00470 static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat(
00471     LPDIRECTSOUNDBUFFER8 iface,
00472     LPWAVEFORMATEX lpwf,
00473     DWORD wfsize,
00474     LPDWORD wfwritten)
00475 {
00476     DWORD size;
00477     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00478     TRACE("(%p,%p,%d,%p)\n",This,lpwf,wfsize,wfwritten);
00479 
00480     size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
00481 
00482     if (lpwf) { /* NULL is valid */
00483         if (wfsize >= size) {
00484             CopyMemory(lpwf,This->pwfx,size);
00485             if (wfwritten)
00486                 *wfwritten = size;
00487         } else {
00488             WARN("invalid parameter: wfsize too small\n");
00489             CopyMemory(lpwf,This->pwfx,wfsize);
00490             if (wfwritten)
00491                 *wfwritten = wfsize;
00492             return DSERR_INVALIDPARAM;
00493         }
00494     } else {
00495         if (wfwritten)
00496             *wfwritten = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
00497         else {
00498             WARN("invalid parameter: wfwritten == NULL\n");
00499             return DSERR_INVALIDPARAM;
00500         }
00501     }
00502 
00503     return DS_OK;
00504 }
00505 
00506 static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
00507     LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID *lplpaudioptr1,LPDWORD audiobytes1,LPVOID *lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
00508 ) {
00509     HRESULT hres = DS_OK;
00510     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00511 
00512     TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n",
00513         This,
00514         writecursor,
00515         writebytes,
00516         lplpaudioptr1,
00517         audiobytes1,
00518         lplpaudioptr2,
00519         audiobytes2,
00520         flags,
00521         GetTickCount()
00522     );
00523 
00524         if (!audiobytes1)
00525             return DSERR_INVALIDPARAM;
00526 
00527         /* when this flag is set, writecursor is meaningless and must be calculated */
00528     if (flags & DSBLOCK_FROMWRITECURSOR) {
00529         /* GetCurrentPosition does too much magic to duplicate here */
00530         hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writecursor);
00531         if (hres != DS_OK) {
00532             WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n");
00533             return hres;
00534         }
00535     }
00536 
00537         /* when this flag is set, writebytes is meaningless and must be set */
00538     if (flags & DSBLOCK_ENTIREBUFFER)
00539         writebytes = This->buflen;
00540 
00541     if (writecursor >= This->buflen) {
00542         WARN("Invalid parameter, writecursor: %u >= buflen: %u\n",
00543              writecursor, This->buflen);
00544         return DSERR_INVALIDPARAM;
00545         }
00546 
00547     if (writebytes > This->buflen) {
00548         WARN("Invalid parameter, writebytes: %u > buflen: %u\n",
00549              writebytes, This->buflen);
00550         return DSERR_INVALIDPARAM;
00551         }
00552 
00553     /* **** */
00554     RtlAcquireResourceShared(&This->lock, TRUE);
00555 
00556     if (!(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
00557         hres = IDsDriverBuffer_Lock(This->hwbuf,
00558                      lplpaudioptr1, audiobytes1,
00559                      lplpaudioptr2, audiobytes2,
00560                      writecursor, writebytes,
00561                      0);
00562         if (hres != DS_OK) {
00563             WARN("IDsDriverBuffer_Lock failed\n");
00564             RtlReleaseResource(&This->lock);
00565             return hres;
00566         }
00567     } else {
00568         if (writecursor+writebytes <= This->buflen) {
00569             *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
00570             if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
00571                 WARN("Overwriting mixing position, case 1\n");
00572             *audiobytes1 = writebytes;
00573             if (lplpaudioptr2)
00574                 *(LPBYTE*)lplpaudioptr2 = NULL;
00575             if (audiobytes2)
00576                 *audiobytes2 = 0;
00577             TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n",
00578               *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
00579             TRACE("->%d.0\n",writebytes);
00580         } else {
00581             DWORD remainder = writebytes + writecursor - This->buflen;
00582             *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
00583             *audiobytes1 = This->buflen-writecursor;
00584             if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
00585                 WARN("Overwriting mixing position, case 2\n");
00586             if (lplpaudioptr2)
00587                 *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
00588             if (audiobytes2)
00589                 *audiobytes2 = writebytes-(This->buflen-writecursor);
00590             if (audiobytes2 && This->sec_mixpos < remainder && This->state == STATE_PLAYING)
00591                 WARN("Overwriting mixing position, case 3\n");
00592             TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
00593         }
00594     }
00595 
00596     RtlReleaseResource(&This->lock);
00597     /* **** */
00598 
00599     return DS_OK;
00600 }
00601 
00602 static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(
00603     LPDIRECTSOUNDBUFFER8 iface,DWORD newpos
00604 ) {
00605     HRESULT hres = DS_OK;
00606     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00607     DWORD oldpos;
00608     TRACE("(%p,%d)\n",This,newpos);
00609 
00610     /* **** */
00611     RtlAcquireResourceExclusive(&This->lock, TRUE);
00612 
00613     oldpos = This->sec_mixpos;
00614 
00615     /* start mixing from this new location instead */
00616     newpos %= This->buflen;
00617     newpos -= newpos%This->pwfx->nBlockAlign;
00618     This->sec_mixpos = newpos;
00619 
00620     /* at this point, do not attempt to reset buffers, mess with primary mix position,
00621            or anything like that to reduce latancy. The data already prebuffered cannot be changed */
00622 
00623     /* position HW buffer if applicable, else just start mixing from new location instead */
00624     if (This->hwbuf) {
00625         hres = IDsDriverBuffer_SetPosition(This->hwbuf, This->buf_mixpos);
00626         if (hres != DS_OK)
00627             WARN("IDsDriverBuffer_SetPosition failed\n");
00628     }
00629     else if (oldpos != newpos)
00630         /* FIXME: Perhaps add a call to DSOUND_MixToTemporary here? Not sure it's needed */
00631         This->buf_mixpos = DSOUND_secpos_to_bufpos(This, newpos, 0, NULL);
00632 
00633     RtlReleaseResource(&This->lock);
00634     /* **** */
00635 
00636     return hres;
00637 }
00638 
00639 static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(
00640     LPDIRECTSOUNDBUFFER8 iface,LONG pan
00641 ) {
00642     HRESULT hres = DS_OK;
00643     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00644 
00645     TRACE("(%p,%d)\n",This,pan);
00646 
00647     if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) {
00648         WARN("invalid parameter: pan = %d\n", pan);
00649         return DSERR_INVALIDPARAM;
00650     }
00651 
00652     /* You cannot use both pan and 3D controls */
00653     if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
00654         (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) {
00655         WARN("control unavailable\n");
00656         return DSERR_CONTROLUNAVAIL;
00657     }
00658 
00659     /* **** */
00660     RtlAcquireResourceExclusive(&This->lock, TRUE);
00661 
00662     if (This->volpan.lPan != pan) {
00663         This->volpan.lPan = pan;
00664         DSOUND_RecalcVolPan(&(This->volpan));
00665 
00666         if (This->hwbuf) {
00667             hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
00668             if (hres != DS_OK)
00669                 WARN("IDsDriverBuffer_SetVolumePan failed\n");
00670         }
00671     }
00672 
00673     RtlReleaseResource(&This->lock);
00674     /* **** */
00675 
00676     return hres;
00677 }
00678 
00679 static HRESULT WINAPI IDirectSoundBufferImpl_GetPan(
00680     LPDIRECTSOUNDBUFFER8 iface,LPLONG pan
00681 ) {
00682     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00683     TRACE("(%p,%p)\n",This,pan);
00684 
00685     if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
00686         WARN("control unavailable\n");
00687         return DSERR_CONTROLUNAVAIL;
00688     }
00689 
00690     if (pan == NULL) {
00691         WARN("invalid parameter: pan = NULL\n");
00692         return DSERR_INVALIDPARAM;
00693     }
00694 
00695     *pan = This->volpan.lPan;
00696 
00697     return DS_OK;
00698 }
00699 
00700 static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(
00701     LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
00702 ) {
00703     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface, *iter;
00704     HRESULT hres = DS_OK;
00705 
00706     TRACE("(%p,%p,%d,%p,%d)\n", This,p1,x1,p2,x2);
00707 
00708     /* **** */
00709     RtlAcquireResourceShared(&This->lock, TRUE);
00710 
00711     if (!(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
00712         hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
00713         if (hres != DS_OK)
00714             WARN("IDsDriverBuffer_Unlock failed\n");
00715     }
00716 
00717     RtlReleaseResource(&This->lock);
00718     /* **** */
00719 
00720     if (!p2)
00721         x2 = 0;
00722 
00723     if (!This->hwbuf && (x1 || x2))
00724     {
00725         RtlAcquireResourceShared(&This->device->buffer_list_lock, TRUE);
00726         LIST_FOR_EACH_ENTRY(iter, &This->buffer->buffers, IDirectSoundBufferImpl, entry )
00727         {
00728             RtlAcquireResourceShared(&iter->lock, TRUE);
00729             if (x1)
00730                         {
00731                 if(x1 + (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory > iter->buflen)
00732                   hres = DSERR_INVALIDPARAM;
00733                 else
00734                   DSOUND_MixToTemporary(iter, (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory, x1, FALSE);
00735                         }
00736             if (x2)
00737                 DSOUND_MixToTemporary(iter, 0, x2, FALSE);
00738             RtlReleaseResource(&iter->lock);
00739         }
00740         RtlReleaseResource(&This->device->buffer_list_lock);
00741     }
00742 
00743     return hres;
00744 }
00745 
00746 static HRESULT WINAPI IDirectSoundBufferImpl_Restore(
00747     LPDIRECTSOUNDBUFFER8 iface
00748 ) {
00749     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00750     FIXME("(%p):stub\n",This);
00751     return DS_OK;
00752 }
00753 
00754 static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(
00755     LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq
00756 ) {
00757     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00758     TRACE("(%p,%p)\n",This,freq);
00759 
00760     if (freq == NULL) {
00761         WARN("invalid parameter: freq = NULL\n");
00762         return DSERR_INVALIDPARAM;
00763     }
00764 
00765     *freq = This->freq;
00766     TRACE("-> %d\n", *freq);
00767 
00768     return DS_OK;
00769 }
00770 
00771 static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(
00772     LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes
00773 ) {
00774     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00775     DWORD u;
00776 
00777     FIXME("(%p,%u,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
00778 
00779     if (pdwResultCodes)
00780         for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
00781 
00782     WARN("control unavailable\n");
00783     return DSERR_CONTROLUNAVAIL;
00784 }
00785 
00786 static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(
00787     LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes
00788 ) {
00789     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00790     DWORD u;
00791 
00792     FIXME("(%p,%08u,%u,%p): stub\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
00793 
00794     if (pdwResultCodes)
00795         for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
00796 
00797     WARN("control unavailable\n");
00798     return DSERR_CONTROLUNAVAIL;
00799 }
00800 
00801 static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(
00802     LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject
00803 ) {
00804     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00805 
00806     FIXME("(%p,%s,%u,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
00807 
00808     WARN("control unavailable\n");
00809     return DSERR_CONTROLUNAVAIL;
00810 }
00811 
00812 static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(
00813     LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND dsound,LPCDSBUFFERDESC dbsd
00814 ) {
00815     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00816     WARN("(%p) already initialized\n", This);
00817     return DSERR_ALREADYINITIALIZED;
00818 }
00819 
00820 static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(
00821     LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps
00822 ) {
00823     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00824     TRACE("(%p)->(%p)\n",This,caps);
00825 
00826     if (caps == NULL) {
00827         WARN("invalid parameter: caps == NULL\n");
00828         return DSERR_INVALIDPARAM;
00829     }
00830 
00831     if (caps->dwSize < sizeof(*caps)) {
00832         WARN("invalid parameter: caps->dwSize = %d\n",caps->dwSize);
00833         return DSERR_INVALIDPARAM;
00834     }
00835 
00836     caps->dwFlags = This->dsbd.dwFlags;
00837     if (This->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
00838     else caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
00839 
00840     caps->dwBufferBytes = This->buflen;
00841 
00842     /* According to windows, this is zero*/
00843     caps->dwUnlockTransferRate = 0;
00844     caps->dwPlayCpuOverhead = 0;
00845 
00846     return DS_OK;
00847 }
00848 
00849 static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
00850     LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj
00851 ) {
00852     IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface;
00853 
00854     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00855 
00856     if (ppobj == NULL) {
00857         WARN("invalid parameter\n");
00858         return E_INVALIDARG;
00859     }
00860 
00861     *ppobj = NULL;  /* assume failure */
00862 
00863     if ( IsEqualGUID(riid, &IID_IUnknown) ||
00864          IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
00865          IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
00866         if (!This->secondary)
00867             SecondaryBufferImpl_Create(This, &(This->secondary));
00868         if (This->secondary) {
00869             IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->secondary);
00870             *ppobj = This->secondary;
00871             return S_OK;
00872         }
00873         WARN("IID_IDirectSoundBuffer\n");
00874         return E_NOINTERFACE;
00875     }
00876 
00877     if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
00878         if (!This->notify)
00879             IDirectSoundNotifyImpl_Create(This, &(This->notify));
00880         if (This->notify) {
00881             IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
00882             *ppobj = This->notify;
00883             return S_OK;
00884         }
00885         WARN("IID_IDirectSoundNotify\n");
00886         return E_NOINTERFACE;
00887     }
00888 
00889     if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
00890         if (!This->ds3db)
00891             IDirectSound3DBufferImpl_Create(This, &(This->ds3db));
00892         if (This->ds3db) {
00893             IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->ds3db);
00894             *ppobj = This->ds3db;
00895             return S_OK;
00896         }
00897         WARN("IID_IDirectSound3DBuffer\n");
00898         return E_NOINTERFACE;
00899     }
00900 
00901     if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
00902         ERR("app requested IDirectSound3DListener on secondary buffer\n");
00903         return E_NOINTERFACE;
00904     }
00905 
00906     if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
00907         if (!This->iks)
00908             IKsBufferPropertySetImpl_Create(This, &(This->iks));
00909         if (This->iks) {
00910             IKsPropertySet_AddRef((LPKSPROPERTYSET)This->iks);
00911                 *ppobj = This->iks;
00912             return S_OK;
00913         }
00914         WARN("IID_IKsPropertySet\n");
00915         return E_NOINTERFACE;
00916     }
00917 
00918     FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
00919 
00920     return E_NOINTERFACE;
00921 }
00922 
00923 static const IDirectSoundBuffer8Vtbl dsbvt =
00924 {
00925     IDirectSoundBufferImpl_QueryInterface,
00926     IDirectSoundBufferImpl_AddRef,
00927     IDirectSoundBufferImpl_Release,
00928     IDirectSoundBufferImpl_GetCaps,
00929     IDirectSoundBufferImpl_GetCurrentPosition,
00930     IDirectSoundBufferImpl_GetFormat,
00931     IDirectSoundBufferImpl_GetVolume,
00932     IDirectSoundBufferImpl_GetPan,
00933     IDirectSoundBufferImpl_GetFrequency,
00934     IDirectSoundBufferImpl_GetStatus,
00935     IDirectSoundBufferImpl_Initialize,
00936     IDirectSoundBufferImpl_Lock,
00937     IDirectSoundBufferImpl_Play,
00938     IDirectSoundBufferImpl_SetCurrentPosition,
00939     IDirectSoundBufferImpl_SetFormat,
00940     IDirectSoundBufferImpl_SetVolume,
00941     IDirectSoundBufferImpl_SetPan,
00942     IDirectSoundBufferImpl_SetFrequency,
00943     IDirectSoundBufferImpl_Stop,
00944     IDirectSoundBufferImpl_Unlock,
00945     IDirectSoundBufferImpl_Restore,
00946     IDirectSoundBufferImpl_SetFX,
00947     IDirectSoundBufferImpl_AcquireResources,
00948     IDirectSoundBufferImpl_GetObjectInPath
00949 };
00950 
00951 HRESULT IDirectSoundBufferImpl_Create(
00952     DirectSoundDevice * device,
00953     IDirectSoundBufferImpl **pdsb,
00954     LPCDSBUFFERDESC dsbd)
00955 {
00956     IDirectSoundBufferImpl *dsb;
00957     LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
00958     HRESULT err = DS_OK;
00959     DWORD capf = 0;
00960     int use_hw, alloc_size, cp_size;
00961     TRACE("(%p,%p,%p)\n",device,pdsb,dsbd);
00962 
00963     if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
00964         WARN("invalid parameter: dsbd->dwBufferBytes = %d\n", dsbd->dwBufferBytes);
00965         *pdsb = NULL;
00966         return DSERR_INVALIDPARAM; /* FIXME: which error? */
00967     }
00968 
00969     dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
00970 
00971     if (dsb == 0) {
00972         WARN("out of memory\n");
00973         *pdsb = NULL;
00974         return DSERR_OUTOFMEMORY;
00975     }
00976 
00977     TRACE("Created buffer at %p\n", dsb);
00978 
00979     dsb->ref = 0;
00980     dsb->secondary = 0;
00981     dsb->device = device;
00982     dsb->lpVtbl = &dsbvt;
00983     dsb->iks = NULL;
00984 
00985     /* size depends on version */
00986     CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize);
00987 
00988     /* variable sized struct so calculate size based on format */
00989     if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
00990         alloc_size = sizeof(WAVEFORMATEX);
00991         cp_size = sizeof(PCMWAVEFORMAT);
00992     } else 
00993         alloc_size = cp_size = sizeof(WAVEFORMATEX) + wfex->cbSize;
00994 
00995     dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,alloc_size);
00996     if (dsb->pwfx == NULL) {
00997         WARN("out of memory\n");
00998         HeapFree(GetProcessHeap(),0,dsb);
00999         *pdsb = NULL;
01000         return DSERR_OUTOFMEMORY;
01001     }
01002 
01003     CopyMemory(dsb->pwfx, wfex, cp_size);
01004 
01005     if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign)
01006         dsb->buflen = dsbd->dwBufferBytes + 
01007             (dsbd->lpwfxFormat->nBlockAlign - 
01008             (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign));
01009     else
01010         dsb->buflen = dsbd->dwBufferBytes;
01011 
01012     dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
01013     dsb->notify = NULL;
01014     dsb->notifies = NULL;
01015     dsb->nrofnotifies = 0;
01016     dsb->hwnotify = 0;
01017 
01018     /* Check necessary hardware mixing capabilities */
01019     if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
01020     else capf |= DSCAPS_SECONDARYMONO;
01021     if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
01022     else capf |= DSCAPS_SECONDARY8BIT;
01023 
01024     use_hw = !!(dsbd->dwFlags & DSBCAPS_LOCHARDWARE);
01025     TRACE("use_hw = %d, capf = 0x%08x, device->drvcaps.dwFlags = 0x%08x\n", use_hw, capf, device->drvcaps.dwFlags);
01026     if (use_hw && ((device->drvcaps.dwFlags & capf) != capf || !device->driver))
01027     {
01028         if (device->driver)
01029             WARN("Format not supported for hardware buffer\n");
01030         HeapFree(GetProcessHeap(),0,dsb->pwfx);
01031         HeapFree(GetProcessHeap(),0,dsb);
01032         *pdsb = NULL;
01033         if ((device->drvcaps.dwFlags & capf) != capf)
01034             return DSERR_BADFORMAT;
01035         return DSERR_GENERIC;
01036     }
01037 
01038     /* FIXME: check hardware sample rate mixing capabilities */
01039     /* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */
01040     /* FIXME: check whether any hardware buffers are left */
01041     /* FIXME: handle DSDHEAP_CREATEHEAP for hardware buffers */
01042 
01043     /* Allocate an empty buffer */
01044     dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
01045     if (dsb->buffer == NULL) {
01046         WARN("out of memory\n");
01047         HeapFree(GetProcessHeap(),0,dsb->pwfx);
01048         HeapFree(GetProcessHeap(),0,dsb);
01049         *pdsb = NULL;
01050         return DSERR_OUTOFMEMORY;
01051     }
01052 
01053     /* Allocate system memory for buffer if applicable */
01054     if ((device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
01055         dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
01056         if (dsb->buffer->memory == NULL) {
01057             WARN("out of memory\n");
01058             HeapFree(GetProcessHeap(),0,dsb->pwfx);
01059             HeapFree(GetProcessHeap(),0,dsb->buffer);
01060             HeapFree(GetProcessHeap(),0,dsb);
01061             *pdsb = NULL;
01062             return DSERR_OUTOFMEMORY;
01063         }
01064     }
01065 
01066     /* Allocate the hardware buffer */
01067     if (use_hw) {
01068         err = IDsDriver_CreateSoundBuffer(device->driver,wfex,dsbd->dwFlags,0,
01069                           &(dsb->buflen),&(dsb->buffer->memory),
01070                           (LPVOID*)&(dsb->hwbuf));
01071         if (FAILED(err))
01072         {
01073             WARN("Failed to create hardware secondary buffer: %08x\n", err);
01074             if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)
01075                 HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
01076             HeapFree(GetProcessHeap(),0,dsb->buffer);
01077             HeapFree(GetProcessHeap(),0,dsb->pwfx);
01078             HeapFree(GetProcessHeap(),0,dsb);
01079             *pdsb = NULL;
01080             return DSERR_GENERIC;
01081         }
01082     }
01083 
01084     dsb->buffer->ref = 1;
01085     list_init(&dsb->buffer->buffers);
01086     list_add_head(&dsb->buffer->buffers, &dsb->entry);
01087     FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0);
01088 
01089     /* It's not necessary to initialize values to zero since */
01090     /* we allocated this structure with HEAP_ZERO_MEMORY... */
01091     dsb->buf_mixpos = dsb->sec_mixpos = 0;
01092     dsb->state = STATE_STOPPED;
01093 
01094     dsb->freqAdjust = ((DWORD64)dsb->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec;
01095     dsb->nAvgBytesPerSec = dsb->freq *
01096         dsbd->lpwfxFormat->nBlockAlign;
01097 
01098     /* calculate fragment size and write lead */
01099     DSOUND_RecalcFormat(dsb);
01100 
01101     if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
01102         dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
01103         dsb->ds3db_ds3db.vPosition.x = 0.0;
01104         dsb->ds3db_ds3db.vPosition.y = 0.0;
01105         dsb->ds3db_ds3db.vPosition.z = 0.0;
01106         dsb->ds3db_ds3db.vVelocity.x = 0.0;
01107         dsb->ds3db_ds3db.vVelocity.y = 0.0;
01108         dsb->ds3db_ds3db.vVelocity.z = 0.0;
01109         dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
01110         dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
01111         dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
01112         dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
01113         dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
01114         dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
01115         dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
01116         dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
01117         dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
01118 
01119         dsb->ds3db_need_recalc = FALSE;
01120         DSOUND_Calc3DBuffer(dsb);
01121     } else
01122         DSOUND_RecalcVolPan(&(dsb->volpan));
01123 
01124     RtlInitializeResource(&dsb->lock);
01125 
01126     /* register buffer if not primary */
01127     if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
01128         err = DirectSoundDevice_AddBuffer(device, dsb);
01129         if (err != DS_OK) {
01130             HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
01131             HeapFree(GetProcessHeap(),0,dsb->buffer);
01132             RtlDeleteResource(&dsb->lock);
01133             HeapFree(GetProcessHeap(),0,dsb->pwfx);
01134             HeapFree(GetProcessHeap(),0,dsb);
01135             dsb = NULL;
01136         }
01137     }
01138 
01139     *pdsb = dsb;
01140     return err;
01141 }
01142 
01143 HRESULT IDirectSoundBufferImpl_Destroy(
01144     IDirectSoundBufferImpl *pdsb)
01145 {
01146     TRACE("(%p)\n",pdsb);
01147 
01148     /* This keeps the *_Destroy functions from possibly deleting
01149      * this object until it is ready to be deleted */
01150     IDirectSoundBufferImpl_AddRef((LPDIRECTSOUNDBUFFER8)pdsb);
01151 
01152     if (pdsb->iks) {
01153         WARN("iks not NULL\n");
01154         IKsBufferPropertySetImpl_Destroy(pdsb->iks);
01155         pdsb->iks = NULL;
01156     }
01157 
01158     if (pdsb->ds3db) {
01159         WARN("ds3db not NULL\n");
01160         IDirectSound3DBufferImpl_Destroy(pdsb->ds3db);
01161         pdsb->ds3db = NULL;
01162     }
01163 
01164     if (pdsb->notify) {
01165         WARN("notify not NULL\n");
01166         IDirectSoundNotifyImpl_Destroy(pdsb->notify);
01167         pdsb->notify = NULL;
01168     }
01169 
01170     if (pdsb->secondary) {
01171         WARN("dsb not NULL\n");
01172         SecondaryBufferImpl_Destroy(pdsb->secondary);
01173         pdsb->secondary = NULL;
01174     }
01175 
01176     while (IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)pdsb) > 0);
01177 
01178     return S_OK;
01179 }
01180 
01181 HRESULT IDirectSoundBufferImpl_Duplicate(
01182     DirectSoundDevice *device,
01183     IDirectSoundBufferImpl **ppdsb,
01184     IDirectSoundBufferImpl *pdsb)
01185 {
01186     IDirectSoundBufferImpl *dsb;
01187     HRESULT hres = DS_OK;
01188     int size;
01189     TRACE("(%p,%p,%p)\n", device, pdsb, pdsb);
01190 
01191     dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
01192 
01193     if (dsb == NULL) {
01194         WARN("out of memory\n");
01195         *ppdsb = NULL;
01196         return DSERR_OUTOFMEMORY;
01197     }
01198 
01199     CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
01200 
01201     if (pdsb->hwbuf) {
01202         TRACE("duplicating hardware buffer\n");
01203 
01204         hres = IDsDriver_DuplicateSoundBuffer(device->driver, pdsb->hwbuf,
01205                                               (LPVOID *)&dsb->hwbuf);
01206         if (FAILED(hres)) {
01207             WARN("IDsDriver_DuplicateSoundBuffer failed (%08x)\n", hres);
01208             HeapFree(GetProcessHeap(),0,dsb);
01209             *ppdsb = NULL;
01210             return hres;
01211         }
01212     }
01213 
01214     dsb->buffer->ref++;
01215     list_add_head(&dsb->buffer->buffers, &dsb->entry);
01216     dsb->ref = 0;
01217     dsb->state = STATE_STOPPED;
01218     dsb->buf_mixpos = dsb->sec_mixpos = 0;
01219     dsb->device = device;
01220     dsb->ds3db = NULL;
01221     dsb->iks = NULL; /* FIXME? */
01222     dsb->secondary = NULL;
01223     dsb->tmp_buffer = NULL;
01224     DSOUND_RecalcFormat(dsb);
01225     DSOUND_MixToTemporary(dsb, 0, dsb->buflen, FALSE);
01226 
01227     /* variable sized struct so calculate size based on format */
01228     size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
01229 
01230     dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
01231     if (dsb->pwfx == NULL) {
01232             WARN("out of memory\n");
01233             HeapFree(GetProcessHeap(),0,dsb->buffer);
01234             HeapFree(GetProcessHeap(),0,dsb);
01235             *ppdsb = NULL;
01236             return DSERR_OUTOFMEMORY;
01237     }
01238 
01239     CopyMemory(dsb->pwfx, pdsb->pwfx, size);
01240 
01241     RtlInitializeResource(&dsb->lock);
01242 
01243     /* register buffer */
01244     hres = DirectSoundDevice_AddBuffer(device, dsb);
01245     if (hres != DS_OK) {
01246         RtlDeleteResource(&dsb->lock);
01247         HeapFree(GetProcessHeap(),0,dsb->tmp_buffer);
01248         HeapFree(GetProcessHeap(),0,dsb->buffer);
01249         HeapFree(GetProcessHeap(),0,dsb->pwfx);
01250         HeapFree(GetProcessHeap(),0,dsb);
01251         *ppdsb = 0;
01252     }
01253 
01254     *ppdsb = dsb;
01255     return hres;
01256 }
01257 
01258 /*******************************************************************************
01259  *      SecondaryBuffer
01260  */
01261 
01262 static HRESULT WINAPI SecondaryBufferImpl_QueryInterface(
01263     LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj)
01264 {
01265     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01266     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
01267 
01268     return IDirectSoundBufferImpl_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb,riid,ppobj);
01269 }
01270 
01271 static ULONG WINAPI SecondaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface)
01272 {
01273     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01274     ULONG ref = InterlockedIncrement(&(This->ref));
01275     TRACE("(%p) ref was %d\n", This, ref - 1);
01276     return ref;
01277 }
01278 
01279 static ULONG WINAPI SecondaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface)
01280 {
01281     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01282     ULONG ref;
01283     TRACE("(%p)\n", This);
01284     ref = InterlockedDecrement(&(This->ref));
01285     TRACE("ref was %d\n", ref + 1);
01286 
01287     if (!ref) {
01288         This->dsb->secondary = NULL;
01289         IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
01290         HeapFree(GetProcessHeap(), 0, This);
01291         TRACE("(%p) released\n", This);
01292     }
01293     return ref;
01294 }
01295 
01296 static HRESULT WINAPI SecondaryBufferImpl_GetCaps(
01297     LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps)
01298 {
01299     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01300     TRACE("(%p)->(%p)\n",This,caps);
01301 
01302     return IDirectSoundBufferImpl_GetCaps((LPDIRECTSOUNDBUFFER8)This->dsb,caps);
01303 }
01304 
01305 static HRESULT WINAPI SecondaryBufferImpl_GetCurrentPosition(
01306     LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos)
01307 {
01308     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01309     TRACE("(%p,%p,%p)\n",This,playpos,writepos);
01310 
01311     return IDirectSoundBufferImpl_GetCurrentPosition((LPDIRECTSOUNDBUFFER8)This->dsb,playpos,writepos);
01312 }
01313 
01314 static HRESULT WINAPI SecondaryBufferImpl_GetFormat(
01315     LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten)
01316 {
01317     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01318     TRACE("(%p,%p,%d,%p)\n",This,lpwf,wfsize,wfwritten);
01319 
01320     return IDirectSoundBufferImpl_GetFormat((LPDIRECTSOUNDBUFFER8)This->dsb,lpwf,wfsize,wfwritten);
01321 }
01322 
01323 static HRESULT WINAPI SecondaryBufferImpl_GetVolume(
01324     LPDIRECTSOUNDBUFFER8 iface,LPLONG vol)
01325 {
01326     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01327     TRACE("(%p,%p)\n",This,vol);
01328 
01329     return IDirectSoundBufferImpl_GetVolume((LPDIRECTSOUNDBUFFER8)This->dsb,vol);
01330 }
01331 
01332 static HRESULT WINAPI SecondaryBufferImpl_GetPan(
01333     LPDIRECTSOUNDBUFFER8 iface,LPLONG pan)
01334 {
01335     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01336     TRACE("(%p,%p)\n",This,pan);
01337 
01338     return IDirectSoundBufferImpl_GetPan((LPDIRECTSOUNDBUFFER8)This->dsb,pan);
01339 }
01340 
01341 static HRESULT WINAPI SecondaryBufferImpl_GetFrequency(
01342     LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq)
01343 {
01344     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01345     TRACE("(%p,%p)\n",This,freq);
01346 
01347     return IDirectSoundBufferImpl_GetFrequency((LPDIRECTSOUNDBUFFER8)This->dsb,freq);
01348 }
01349 
01350 static HRESULT WINAPI SecondaryBufferImpl_GetStatus(
01351     LPDIRECTSOUNDBUFFER8 iface,LPDWORD status)
01352 {
01353     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01354     TRACE("(%p,%p)\n",This,status);
01355 
01356     return IDirectSoundBufferImpl_GetStatus((LPDIRECTSOUNDBUFFER8)This->dsb,status);
01357 }
01358 
01359 static HRESULT WINAPI SecondaryBufferImpl_Initialize(
01360     LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND dsound,LPCDSBUFFERDESC dbsd)
01361 {
01362     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01363     TRACE("(%p,%p,%p)\n",This,dsound,dbsd);
01364 
01365     return IDirectSoundBufferImpl_Initialize((LPDIRECTSOUNDBUFFER8)This->dsb,dsound,dbsd);
01366 }
01367 
01368 static HRESULT WINAPI SecondaryBufferImpl_Lock(
01369     LPDIRECTSOUNDBUFFER8 iface,
01370     DWORD writecursor,
01371     DWORD writebytes,
01372     LPVOID *lplpaudioptr1,
01373     LPDWORD audiobytes1,
01374     LPVOID *lplpaudioptr2,
01375     LPDWORD audiobytes2,
01376     DWORD dwFlags)
01377 {
01378     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01379     TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x)\n",
01380         This,writecursor,writebytes,lplpaudioptr1,audiobytes1,lplpaudioptr2,audiobytes2,dwFlags);
01381 
01382     return IDirectSoundBufferImpl_Lock((LPDIRECTSOUNDBUFFER8)This->dsb,
01383         writecursor,writebytes,lplpaudioptr1,audiobytes1,lplpaudioptr2,audiobytes2,dwFlags);
01384 }
01385 
01386 static HRESULT WINAPI SecondaryBufferImpl_Play(
01387     LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags)
01388 {
01389     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01390     TRACE("(%p,%08x,%08x,%08x)\n",This,reserved1,reserved2,flags);
01391 
01392     return IDirectSoundBufferImpl_Play((LPDIRECTSOUNDBUFFER8)This->dsb,reserved1,reserved2,flags);
01393 }
01394 
01395 static HRESULT WINAPI SecondaryBufferImpl_SetCurrentPosition(
01396     LPDIRECTSOUNDBUFFER8 iface,DWORD newpos)
01397 {
01398     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01399     TRACE("(%p,%d)\n",This,newpos);
01400 
01401     return IDirectSoundBufferImpl_SetCurrentPosition((LPDIRECTSOUNDBUFFER8)This->dsb,newpos);
01402 }
01403 
01404 static HRESULT WINAPI SecondaryBufferImpl_SetFormat(
01405     LPDIRECTSOUNDBUFFER8 iface,LPCWAVEFORMATEX wfex)
01406 {
01407     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01408     TRACE("(%p,%p)\n",This,wfex);
01409 
01410     return IDirectSoundBufferImpl_SetFormat((LPDIRECTSOUNDBUFFER8)This->dsb,wfex);
01411 }
01412 
01413 static HRESULT WINAPI SecondaryBufferImpl_SetVolume(
01414     LPDIRECTSOUNDBUFFER8 iface,LONG vol)
01415 {
01416     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01417     TRACE("(%p,%d)\n",This,vol);
01418 
01419     return IDirectSoundBufferImpl_SetVolume((LPDIRECTSOUNDBUFFER8)This->dsb,vol);
01420 }
01421 
01422 static HRESULT WINAPI SecondaryBufferImpl_SetPan(
01423     LPDIRECTSOUNDBUFFER8 iface,LONG pan)
01424 {
01425     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01426     TRACE("(%p,%d)\n",This,pan);
01427 
01428     return IDirectSoundBufferImpl_SetPan((LPDIRECTSOUNDBUFFER8)This->dsb,pan);
01429 }
01430 
01431 static HRESULT WINAPI SecondaryBufferImpl_SetFrequency(
01432     LPDIRECTSOUNDBUFFER8 iface,DWORD freq)
01433 {
01434     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01435     TRACE("(%p,%d)\n",This,freq);
01436 
01437     return IDirectSoundBufferImpl_SetFrequency((LPDIRECTSOUNDBUFFER8)This->dsb,freq);
01438 }
01439 
01440 static HRESULT WINAPI SecondaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface)
01441 {
01442     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01443     TRACE("(%p)\n",This);
01444 
01445     return IDirectSoundBufferImpl_Stop((LPDIRECTSOUNDBUFFER8)This->dsb);
01446 }
01447 
01448 static HRESULT WINAPI SecondaryBufferImpl_Unlock(
01449     LPDIRECTSOUNDBUFFER8 iface,
01450     LPVOID lpvAudioPtr1,
01451     DWORD dwAudioBytes1,
01452     LPVOID lpvAudioPtr2,
01453     DWORD dwAudioBytes2)
01454 {
01455     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01456     TRACE("(%p,%p,%d,%p,%d)\n",
01457         This, lpvAudioPtr1, dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
01458 
01459     return IDirectSoundBufferImpl_Unlock((LPDIRECTSOUNDBUFFER8)This->dsb,
01460         lpvAudioPtr1,dwAudioBytes1,lpvAudioPtr2,dwAudioBytes2);
01461 }
01462 
01463 static HRESULT WINAPI SecondaryBufferImpl_Restore(
01464     LPDIRECTSOUNDBUFFER8 iface)
01465 {
01466     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01467     TRACE("(%p)\n",This);
01468 
01469     return IDirectSoundBufferImpl_Restore((LPDIRECTSOUNDBUFFER8)This->dsb);
01470 }
01471 
01472 static HRESULT WINAPI SecondaryBufferImpl_SetFX(
01473     LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes)
01474 {
01475     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01476     TRACE("(%p,%u,%p,%p)\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
01477 
01478     return IDirectSoundBufferImpl_SetFX((LPDIRECTSOUNDBUFFER8)This->dsb,dwEffectsCount,pDSFXDesc,pdwResultCodes);
01479 }
01480 
01481 static HRESULT WINAPI SecondaryBufferImpl_AcquireResources(
01482     LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes)
01483 {
01484     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01485     TRACE("(%p,%08u,%u,%p)\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
01486 
01487     return IDirectSoundBufferImpl_AcquireResources((LPDIRECTSOUNDBUFFER8)This->dsb,dwFlags,dwEffectsCount,pdwResultCodes);
01488 }
01489 
01490 static HRESULT WINAPI SecondaryBufferImpl_GetObjectInPath(
01491     LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject)
01492 {
01493     SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface;
01494     TRACE("(%p,%s,%u,%s,%p)\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
01495 
01496     return IDirectSoundBufferImpl_GetObjectInPath((LPDIRECTSOUNDBUFFER8)This->dsb,rguidObject,dwIndex,rguidInterface,ppObject);
01497 }
01498 
01499 static const IDirectSoundBuffer8Vtbl sbvt =
01500 {
01501     SecondaryBufferImpl_QueryInterface,
01502     SecondaryBufferImpl_AddRef,
01503     SecondaryBufferImpl_Release,
01504     SecondaryBufferImpl_GetCaps,
01505     SecondaryBufferImpl_GetCurrentPosition,
01506     SecondaryBufferImpl_GetFormat,
01507     SecondaryBufferImpl_GetVolume,
01508     SecondaryBufferImpl_GetPan,
01509     SecondaryBufferImpl_GetFrequency,
01510     SecondaryBufferImpl_GetStatus,
01511     SecondaryBufferImpl_Initialize,
01512     SecondaryBufferImpl_Lock,
01513     SecondaryBufferImpl_Play,
01514     SecondaryBufferImpl_SetCurrentPosition,
01515     SecondaryBufferImpl_SetFormat,
01516     SecondaryBufferImpl_SetVolume,
01517     SecondaryBufferImpl_SetPan,
01518     SecondaryBufferImpl_SetFrequency,
01519     SecondaryBufferImpl_Stop,
01520     SecondaryBufferImpl_Unlock,
01521     SecondaryBufferImpl_Restore,
01522     SecondaryBufferImpl_SetFX,
01523     SecondaryBufferImpl_AcquireResources,
01524     SecondaryBufferImpl_GetObjectInPath
01525 };
01526 
01527 HRESULT SecondaryBufferImpl_Create(
01528     IDirectSoundBufferImpl *dsb,
01529     SecondaryBufferImpl **psb)
01530 {
01531     SecondaryBufferImpl *sb;
01532     TRACE("(%p,%p)\n",dsb,psb);
01533 
01534     sb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*sb));
01535 
01536     if (sb == 0) {
01537         WARN("out of memory\n");
01538         *psb = NULL;
01539         return DSERR_OUTOFMEMORY;
01540     }
01541     sb->ref = 0;
01542     sb->dsb = dsb;
01543     sb->lpVtbl = &sbvt;
01544 
01545     IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
01546     *psb = sb;
01547     return S_OK;
01548 }
01549 
01550 static HRESULT SecondaryBufferImpl_Destroy(
01551     SecondaryBufferImpl *pdsb)
01552 {
01553     TRACE("(%p)\n",pdsb);
01554 
01555     while (SecondaryBufferImpl_Release((LPDIRECTSOUNDBUFFER8)pdsb) > 0);
01556 
01557     return S_OK;
01558 }

Generated on Sat May 26 2012 04:20:06 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.