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 + -
显示快捷键?