buffer.c
来自「一个类似windows」· C语言 代码 · 共 1,512 行 · 第 1/3 页
C
1,512 行
*status |= DSBSTATUS_PLAYING; if (This->playflags & DSBPLAY_LOOPING) *status |= DSBSTATUS_LOOPING; } TRACE("status=%lx\n", *status); return DS_OK;}static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat( LPDIRECTSOUNDBUFFER8 iface, LPWAVEFORMATEX lpwf, DWORD wfsize, LPDWORD wfwritten){ DWORD size; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten); size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize; if (lpwf) { /* NULL is valid */ if (wfsize >= size) { CopyMemory(lpwf,This->pwfx,size); if (wfwritten) *wfwritten = size; } else { WARN("invalid parameter: wfsize too small\n"); if (wfwritten) *wfwritten = 0; return DSERR_INVALIDPARAM; } } else { if (wfwritten) *wfwritten = sizeof(WAVEFORMATEX) + This->pwfx->cbSize; else { WARN("invalid parameter: wfwritten == NULL\n"); return DSERR_INVALIDPARAM; } } return DS_OK;}static HRESULT WINAPI IDirectSoundBufferImpl_Lock( LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags) { HRESULT hres = DS_OK; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx) at %ld\n", This, writecursor, writebytes, lplpaudioptr1, audiobytes1, lplpaudioptr2, audiobytes2, flags, GetTickCount() ); if (flags & DSBLOCK_FROMWRITECURSOR) { DWORD writepos; /* GetCurrentPosition does too much magic to duplicate here */ hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writepos); if (hres != DS_OK) { WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n"); return hres; } writecursor += writepos; } writecursor %= This->buflen; if (flags & DSBLOCK_ENTIREBUFFER) writebytes = This->buflen; if (writebytes > This->buflen) writebytes = This->buflen; EnterCriticalSection(&(This->lock)); if ((writebytes == This->buflen) && ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING))) /* some games, like Half-Life, try to be clever (not) and * keep one secondary buffer, and mix sounds into it itself, * locking the entire buffer every time... so we can just forget * about tracking the last-written-to-position... */ This->probably_valid_to = (DWORD)-1; else This->probably_valid_to = writecursor; if (!(This->dsound->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) { hres = IDsDriverBuffer_Lock(This->hwbuf, lplpaudioptr1, audiobytes1, lplpaudioptr2, audiobytes2, writecursor, writebytes, 0); if (hres != DS_OK) { WARN("IDsDriverBuffer_Lock failed\n"); LeaveCriticalSection(&(This->lock)); return hres; } } else { BOOL remix = FALSE; if (writecursor+writebytes <= This->buflen) { *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor; *audiobytes1 = writebytes; if (lplpaudioptr2) *(LPBYTE*)lplpaudioptr2 = NULL; if (audiobytes2) *audiobytes2 = 0; TRACE("->%ld.0\n",writebytes); } else { *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor; *audiobytes1 = This->buflen-writecursor; if (lplpaudioptr2) *(LPBYTE*)lplpaudioptr2 = This->buffer->memory; if (audiobytes2) *audiobytes2 = writebytes-(This->buflen-writecursor); TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0); } if (This->state == STATE_PLAYING) { /* if the segment between playpos and buf_mixpos is touched, * we need to cancel some mixing */ /* we'll assume that the app always calls GetCurrentPosition before * locking a playing buffer, so that last_playpos is up-to-date */ if (This->buf_mixpos >= This->last_playpos) { if (This->buf_mixpos > writecursor && This->last_playpos < writecursor+writebytes) remix = TRUE; } else { if (This->buf_mixpos > writecursor || This->last_playpos < writecursor+writebytes) remix = TRUE; } if (remix) { TRACE("locking prebuffered region, ouch\n"); DSOUND_MixCancelAt(This, writecursor); } } } LeaveCriticalSection(&(This->lock)); return DS_OK;}static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition( LPDIRECTSOUNDBUFFER8 iface,DWORD newpos) { HRESULT hres = DS_OK; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; TRACE("(%p,%ld)\n",This,newpos); /* **** */ EnterCriticalSection(&(This->lock)); newpos %= This->buflen; This->buf_mixpos = newpos; if (This->hwbuf) { hres = IDsDriverBuffer_SetPosition(This->hwbuf, This->buf_mixpos); if (hres != DS_OK) WARN("IDsDriverBuffer_SetPosition failed\n"); } LeaveCriticalSection(&(This->lock)); /* **** */ return hres;}static HRESULT WINAPI IDirectSoundBufferImpl_SetPan( LPDIRECTSOUNDBUFFER8 iface,LONG pan) { HRESULT hres = DS_OK; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; TRACE("(%p,%ld)\n",This,pan); if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) { WARN("invalid parameter: pan = %ld\n", pan); return DSERR_INVALIDPARAM; } /* You cannot use both pan and 3D controls */ if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) || (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) { WARN("control unavailable\n"); return DSERR_CONTROLUNAVAIL; } /* **** */ EnterCriticalSection(&(This->lock)); if (This->volpan.lPan != pan) { This->volpan.lPan = pan; DSOUND_RecalcVolPan(&(This->volpan)); if (This->hwbuf) { hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan)); if (hres != DS_OK) WARN("IDsDriverBuffer_SetVolumePan failed\n"); } else DSOUND_ForceRemix(This); } LeaveCriticalSection(&(This->lock)); /* **** */ return hres;}static HRESULT WINAPI IDirectSoundBufferImpl_GetPan( LPDIRECTSOUNDBUFFER8 iface,LPLONG pan) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; TRACE("(%p,%p)\n",This,pan); if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) { WARN("control unavailable\n"); return DSERR_CONTROLUNAVAIL; } if (pan == NULL) { WARN("invalid parameter: pan = NULL\n"); return DSERR_INVALIDPARAM; } *pan = This->volpan.lPan; return DS_OK;}static HRESULT WINAPI IDirectSoundBufferImpl_Unlock( LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; DWORD probably_valid_to; HRESULT hres = DS_OK; TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2); /* **** */ EnterCriticalSection(&(This->lock)); if (!(This->dsound->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) { hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2); if (hres != DS_OK) WARN("IDsDriverBuffer_Unlock failed\n"); } if (hres == DS_OK) { if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer->memory) + x2; else probably_valid_to = (((LPBYTE)p1)-This->buffer->memory) + x1; probably_valid_to %= This->buflen; if ((probably_valid_to == 0) && ((x1+x2) == This->buflen) && ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING))) /* see IDirectSoundBufferImpl_Lock */ probably_valid_to = (DWORD)-1; This->probably_valid_to = probably_valid_to; } LeaveCriticalSection(&(This->lock)); /* **** */ TRACE("probably_valid_to=%ld\n", This->probably_valid_to); return hres;}static HRESULT WINAPI IDirectSoundBufferImpl_Restore( LPDIRECTSOUNDBUFFER8 iface) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; FIXME("(%p):stub\n",This); return DS_OK;}static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency( LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; TRACE("(%p,%p)\n",This,freq); if (freq == NULL) { WARN("invalid parameter: freq = NULL\n"); return DSERR_INVALIDPARAM; } *freq = This->freq; TRACE("-> %ld\n", *freq); return DS_OK;}static HRESULT WINAPI IDirectSoundBufferImpl_SetFX( LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; DWORD u; FIXME("(%p,%lu,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes); if (pdwResultCodes) for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN; WARN("control unavailable\n"); return DSERR_CONTROLUNAVAIL;}static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources( LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; DWORD u; FIXME("(%p,%08lu,%lu,%p): stub\n",This,dwFlags,dwEffectsCount,pdwResultCodes); if (pdwResultCodes) for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN; WARN("control unavailable\n"); return DSERR_CONTROLUNAVAIL;}static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath( LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; FIXME("(%p,%s,%lu,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject); WARN("control unavailable\n"); return DSERR_CONTROLUNAVAIL;}static HRESULT WINAPI IDirectSoundBufferImpl_Initialize( LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND dsound,LPCDSBUFFERDESC dbsd) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; FIXME("(%p,%p,%p):stub\n",This,dsound,dbsd); DPRINTF("Re-Init!!!\n"); WARN("already initialized\n"); return DSERR_ALREADYINITIALIZED;}static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps( LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; TRACE("(%p)->(%p)\n",This,caps); if (caps == NULL) { WARN("invalid parameter: caps == NULL\n"); return DSERR_INVALIDPARAM; } if (caps->dwSize < sizeof(*caps)) { WARN("invalid parameter: caps->dwSize = %ld < %d\n",caps->dwSize, sizeof(*caps)); return DSERR_INVALIDPARAM; } caps->dwFlags = This->dsbd.dwFlags; if (This->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE; else caps->dwFlags |= DSBCAPS_LOCSOFTWARE; caps->dwBufferBytes = This->buflen; /* This value represents the speed of the "unlock" command. As unlock is quite fast (it does not do anything), I put 4096 ko/s = 4 Mo / s */ /* FIXME: hwbuf speed */ caps->dwUnlockTransferRate = 4096; caps->dwPlayCpuOverhead = 0; return DS_OK;}static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); if (ppobj == NULL) { WARN("invalid parameter\n"); return E_INVALIDARG; } *ppobj = NULL; /* assume failure */ if ( IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectSoundBuffer) || IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) { if (!This->dsb) SecondaryBufferImpl_Create(This, &(This->dsb)); if (This->dsb) { IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb); *ppobj = This->dsb; return S_OK; } WARN("IID_IDirectSoundBuffer\n"); return E_NOINTERFACE; } if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) { if (!This->notify) IDirectSoundNotifyImpl_Create(This, &(This->notify)); if (This->notify) { IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify); *ppobj = This->notify; return S_OK; } WARN("IID_IDirectSoundNotify\n"); return E_NOINTERFACE; } if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) { if (!This->ds3db) IDirectSound3DBufferImpl_Create(This, &(This->ds3db)); if (This->ds3db) { IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->ds3db); *ppobj = This->ds3db; return S_OK; } WARN("IID_IDirectSound3DBuffer\n"); return E_NOINTERFACE; } if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) { ERR("app requested IDirectSound3DListener on secondary buffer\n"); return E_NOINTERFACE; } if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) { if (!This->iks) IKsBufferPropertySetImpl_Create(This, &(This->iks)); if (This->iks) { IKsPropertySet_AddRef((LPKSPROPERTYSET)This->iks); *ppobj = This->iks; return S_OK; } WARN("IID_IKsPropertySet\n"); return E_NOINTERFACE; } FIXME( "Unknown IID %s\n", debugstr_guid( riid ) ); return E_NOINTERFACE;}static const IDirectSoundBuffer8Vtbl dsbvt ={ IDirectSoundBufferImpl_QueryInterface, IDirectSoundBufferImpl_AddRef, IDirectSoundBufferImpl_Release, IDirectSoundBufferImpl_GetCaps, IDirectSoundBufferImpl_GetCurrentPosition, IDirectSoundBufferImpl_GetFormat, IDirectSoundBufferImpl_GetVolume, IDirectSoundBufferImpl_GetPan, IDirectSoundBufferImpl_GetFrequency, IDirectSoundBufferImpl_GetStatus, IDirectSoundBufferImpl_Initialize, IDirectSoundBufferImpl_Lock, IDirectSoundBufferImpl_Play, IDirectSoundBufferImpl_SetCurrentPosition, IDirectSoundBufferImpl_SetFormat, IDirectSoundBufferImpl_SetVolume, IDirectSoundBufferImpl_SetPan, IDirectSoundBufferImpl_SetFrequency, IDirectSoundBufferImpl_Stop, IDirectSoundBufferImpl_Unlock, IDirectSoundBufferImpl_Restore, IDirectSoundBufferImpl_SetFX, IDirectSoundBufferImpl_AcquireResources, IDirectSoundBufferImpl_GetObjectInPath};HRESULT WINAPI IDirectSoundBufferImpl_Create( IDirectSoundImpl *ds, IDirectSoundBufferImpl **pdsb, LPCDSBUFFERDESC dsbd){ IDirectSoundBufferImpl *dsb; LPWAVEFORMATEX wfex = dsbd->lpwfxFormat; HRESULT err = DS_OK; DWORD capf = 0; int use_hw, alloc_size, cp_size; TRACE("(%p,%p,%p)\n",ds,pdsb,dsbd); if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) { WARN("invalid parameter: dsbd->dwBufferBytes = %ld\n", dsbd->dwBufferBytes); *pdsb = NULL; return DSERR_INVALIDPARAM; /* FIXME: which error? */ } dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb)); if (dsb == 0) { WARN("out of memory\n"); *pdsb = NULL; return DSERR_OUTOFMEMORY;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?