capture.c

来自「一个类似windows」· C语言 代码 · 共 1,798 行 · 第 1/4 页

C
1,798
字号
}static HRESULT WINAPIIDirectSoundCaptureImpl_QueryInterface(    LPDIRECTSOUNDCAPTURE iface,    REFIID riid,    LPVOID* ppobj ){    IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;    TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );    if (ppobj == NULL) {	WARN("invalid parameter\n");	return E_INVALIDARG;    }    *ppobj = NULL;    if (IsEqualIID(riid, &IID_IUnknown)) {        IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);        *ppobj = This;        return DS_OK;    } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {        IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);        *ppobj = This;        return DS_OK;    }    WARN("unsupported riid: %s\n", debugstr_guid(riid));    return E_NOINTERFACE;}static ULONG WINAPIIDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface ){    IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;    ULONG ref = InterlockedIncrement(&(This->ref));    TRACE("(%p) ref was %ld\n", This, ref - 1);    return ref;}static ULONG DirectSoundCaptureDevice_Release(    DirectSoundCaptureDevice * device){    ULONG ref;    TRACE("(%p) ref was %lu\n", device, device->ref);    device->ref--;    ref=device->ref;    if (device->ref == 0) {        TRACE("deleting object\n");        if (device->capture_buffer)            IDirectSoundCaptureBufferImpl_Release(		(LPDIRECTSOUNDCAPTUREBUFFER8) device->capture_buffer);        if (device->driver) {            IDsCaptureDriver_Close(device->driver);            IDsCaptureDriver_Release(device->driver);        }        HeapFree(GetProcessHeap(), 0, device->pwfx);        device->lock.DebugInfo->Spare[0] = 0;        DeleteCriticalSection( &(device->lock) );        DSOUND_capture[device->drvdesc.dnDevNode] = NULL;        HeapFree(GetProcessHeap(), 0, device);	TRACE("(%p) released\n", device);    }    return ref;}static ULONG WINAPIIDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface ){    IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;    ULONG ref = InterlockedDecrement(&(This->ref));    TRACE("(%p) ref was %ld\n", This, ref + 1);    if (!ref) {        if (This->device)            DirectSoundCaptureDevice_Release(This->device);        HeapFree( GetProcessHeap(), 0, This );	TRACE("(%p) released\n", This);    }    return ref;}static HRESULT WINAPIIDirectSoundCaptureImpl_CreateCaptureBuffer(    LPDIRECTSOUNDCAPTURE iface,    LPCDSCBUFFERDESC lpcDSCBufferDesc,    LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,    LPUNKNOWN pUnk ){    HRESULT hr;    IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;    TRACE( "(%p,%p,%p,%p)\n",iface,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);    if (This == NULL) {	WARN("invalid parameter: This == NULL\n");	return DSERR_INVALIDPARAM;    }    if (lpcDSCBufferDesc == NULL) {	WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");	return DSERR_INVALIDPARAM;    }    if (lplpDSCaptureBuffer == NULL) {	WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");	return DSERR_INVALIDPARAM;    }    if (pUnk != NULL) {	WARN("invalid parameter: pUnk != NULL\n");	return DSERR_INVALIDPARAM;    }    /* FIXME: We can only have one buffer so what do we do here? */    if (This->device->capture_buffer) {	WARN("lnvalid parameter: already has buffer\n");	return DSERR_INVALIDPARAM;    /* DSERR_GENERIC ? */    }    hr = DSOUND_CreateDirectSoundCaptureBuffer(This, lpcDSCBufferDesc,        (LPVOID*)lplpDSCaptureBuffer );    if (hr != DS_OK)	WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n");    return hr;}static HRESULT WINAPIIDirectSoundCaptureImpl_GetCaps(    LPDIRECTSOUNDCAPTURE iface,    LPDSCCAPS lpDSCCaps ){    IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;    TRACE("(%p,%p)\n",This,lpDSCCaps);    if (This->device == NULL) {	WARN("not initialized\n");	return DSERR_UNINITIALIZED;    }    if (lpDSCCaps== NULL) {	WARN("invalid parameter: lpDSCCaps== NULL\n");	return DSERR_INVALIDPARAM;    }    if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {	WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",	    lpDSCCaps->dwSize, sizeof(*lpDSCCaps));	return DSERR_INVALIDPARAM;    }    lpDSCCaps->dwFlags = This->device->drvcaps.dwFlags;    lpDSCCaps->dwFormats = This->device->drvcaps.dwFormats;    lpDSCCaps->dwChannels = This->device->drvcaps.dwChannels;    TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps->dwFlags,        lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);    return DS_OK;}static HRESULT WINAPIIDirectSoundCaptureImpl_Initialize(    LPDIRECTSOUNDCAPTURE iface,    LPCGUID lpcGUID ){    HRESULT err = DSERR_INVALIDPARAM;    unsigned wid, widn;    BOOLEAN found = FALSE;    GUID devGUID;    IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;    DirectSoundCaptureDevice *device = This->device;    TRACE("(%p)\n", This);    if (!This) {	WARN("invalid parameter: This == NULL\n");	return DSERR_INVALIDPARAM;    }    if (device != NULL) {	WARN("already initialized\n");	return DSERR_ALREADYINITIALIZED;    }    /* Default device? */    if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )	lpcGUID = &DSDEVID_DefaultCapture;    if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {        WARN("invalid parameter: lpcGUID\n");        return DSERR_INVALIDPARAM;    }    widn = waveInGetNumDevs();    if (!widn) {	WARN("no audio devices found\n");	return DSERR_NODRIVER;    }    /* enumerate WINMM audio devices and find the one we want */    for (wid=0; wid<widn; wid++) {    	if (IsEqualGUID( &devGUID, &DSOUND_capture_guids[wid]) ) {	    found = TRUE;	    break;	}    }    if (found == FALSE) {	WARN("No device found matching given ID!\n");	return DSERR_NODRIVER;    }    if (DSOUND_capture[wid]) {        WARN("already in use\n");        return DSERR_ALLOCATED;    }    err = DirectSoundCaptureDevice_Create(&(device));    if (err != DS_OK) {        WARN("DirectSoundCaptureDevice_Create failed\n");        return err;    }    This->device = device;    device->guid = devGUID;    err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&(This->device->driver),0));    if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {	WARN("WineWaveInMessage failed; err=%lx\n",err);	return err;    }    err = DS_OK;    /* Disable the direct sound driver to force emulation if requested. */    if (ds_hw_accel == DS_HW_ACCEL_EMULATION)	This->device->driver = NULL;    /* Get driver description */    if (This->device->driver) {        TRACE("using DirectSound driver\n");        err = IDsCaptureDriver_GetDriverDesc(This->device->driver, &(This->device->drvdesc));	if (err != DS_OK) {	    WARN("IDsCaptureDriver_GetDriverDesc failed\n");	    return err;	}    } else {        TRACE("using WINMM\n");        /* if no DirectSound interface available, use WINMM API instead */        This->device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |            DSDDESC_DOMMSYSTEMSETFORMAT;    }    This->device->drvdesc.dnDevNode = wid;    /* open the DirectSound driver if available */    if (This->device->driver && (err == DS_OK))        err = IDsCaptureDriver_Open(This->device->driver);    if (err == DS_OK) {        This->device = device;        /* the driver is now open, so it's now allowed to call GetCaps */        if (This->device->driver) {	    This->device->drvcaps.dwSize = sizeof(This->device->drvcaps);            err = IDsCaptureDriver_GetCaps(This->device->driver,&(This->device->drvcaps));	    if (err != DS_OK) {		WARN("IDsCaptureDriver_GetCaps failed\n");		return err;	    }        } else /*if (This->hwi)*/ {            WAVEINCAPSA    wic;            err = mmErr(waveInGetDevCapsA((UINT)This->device->drvdesc.dnDevNode, &wic, sizeof(wic)));            if (err == DS_OK) {                This->device->drvcaps.dwFlags = 0;                lstrcpynA(This->device->drvdesc.szDrvname, wic.szPname,                          sizeof(This->device->drvdesc.szDrvname));                This->device->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;                This->device->drvcaps.dwFormats = wic.dwFormats;                This->device->drvcaps.dwChannels = wic.wChannels;            }        }    }    return err;}static const IDirectSoundCaptureVtbl dscvt ={    /* IUnknown methods */    IDirectSoundCaptureImpl_QueryInterface,    IDirectSoundCaptureImpl_AddRef,    IDirectSoundCaptureImpl_Release,    /* IDirectSoundCapture methods */    IDirectSoundCaptureImpl_CreateCaptureBuffer,    IDirectSoundCaptureImpl_GetCaps,    IDirectSoundCaptureImpl_Initialize};static HRESULTDSOUND_CreateDirectSoundCaptureBuffer(    IDirectSoundCaptureImpl *ipDSC,    LPCDSCBUFFERDESC lpcDSCBufferDesc,    LPVOID* ppobj ){    LPWAVEFORMATEX  wfex;    TRACE( "(%p,%p)\n", lpcDSCBufferDesc, ppobj );    if (ipDSC == NULL) {	WARN("invalid parameter: ipDSC == NULL\n");	return DSERR_INVALIDPARAM;    }    if (lpcDSCBufferDesc == NULL) {	WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");	return DSERR_INVALIDPARAM;    }    if (ppobj == NULL) {	WARN("invalid parameter: ppobj == NULL\n");	return DSERR_INVALIDPARAM;    }    if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) &&          (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) ||        (lpcDSCBufferDesc->dwBufferBytes == 0) ||        (lpcDSCBufferDesc->lpwfxFormat == NULL) ) {	WARN("invalid lpcDSCBufferDesc\n");	*ppobj = NULL;	return DSERR_INVALIDPARAM;    }    if ( !ipDSC->device) {	WARN("not initialized\n");	*ppobj = NULL;	return DSERR_UNINITIALIZED;    }    wfex = lpcDSCBufferDesc->lpwfxFormat;    if (wfex) {        TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"            "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",            wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,            wfex->nAvgBytesPerSec, wfex->nBlockAlign,            wfex->wBitsPerSample, wfex->cbSize);        if (wfex->wFormatTag == WAVE_FORMAT_PCM) {	    ipDSC->device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX));            CopyMemory(ipDSC->device->pwfx, wfex, sizeof(WAVEFORMATEX));	    ipDSC->device->pwfx->cbSize = 0;	} else {	    ipDSC->device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize);            CopyMemory(ipDSC->device->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize);        }    } else {	WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");	*ppobj = NULL;	return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */    }    *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,        sizeof(IDirectSoundCaptureBufferImpl));    if ( *ppobj == NULL ) {	WARN("out of memory\n");	*ppobj = NULL;	return DSERR_OUTOFMEMORY;    } else {    	HRESULT err = DS_OK;        LPBYTE newbuf;        DWORD buflen;        IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)*ppobj;        This->ref = 1;        This->dsound = ipDSC;        This->dsound->device->capture_buffer = This;	This->notify = NULL;	This->nrofnotifies = 0;	This->hwnotify = NULL;        This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,            lpcDSCBufferDesc->dwSize);        if (This->pdscbd)            CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);        else {            WARN("no memory\n");            This->dsound->device->capture_buffer = 0;            HeapFree( GetProcessHeap(), 0, This );            *ppobj = NULL;            return DSERR_OUTOFMEMORY;        }        This->lpVtbl = &dscbvt;	if (ipDSC->device->driver) {            if (This->dsound->device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)                FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");            if (This->dsound->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {                /* allocate buffer from system memory */                buflen = lpcDSCBufferDesc->dwBufferBytes;                TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->device->buffer);                if (ipDSC->device->buffer)                    newbuf = HeapReAlloc(GetProcessHeap(),0,ipDSC->device->buffer,buflen);                else                    newbuf = HeapAlloc(GetProcessHeap(),0,buflen);                if (newbuf == NULL) {                    WARN("failed to allocate capture buffer\n");                    err = DSERR_OUTOFMEMORY;                    /* but the old buffer might still exist and must be re-prepared */                } else {                    ipDSC->device->buffer = newbuf;                    ipDSC->device->buflen = buflen;                }            } else {                /* let driver allocate memory */                ipDSC->device->buflen = lpcDSCBufferDesc->dwBufferBytes;                /* FIXME: */                HeapFree( GetProcessHeap(), 0, ipDSC->device->buffer);                ipDSC->device->buffer = NULL;            }	    err = IDsCaptureDriver_CreateCaptureBuffer(ipDSC->device->driver,		ipDSC->device->pwfx,0,0,&(ipDSC->device->buflen),&(ipDSC->device->buffer),(LPVOID*)&(ipDSC->device->hwbuf));	    if (err != DS_OK) {		WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");		This->dsound->device->capture_buffer = 0;		HeapFree( GetProcessHeap(), 0, This );		*ppobj = NULL;		return err;	    }	} else {	    DWORD flags = CALLBACK_FUNCTION;	    if (ds_hw_accel != DS_HW_ACCEL_EMULATION)		flags |= WAVE_DIRECTSOUND;            err = mmErr(waveInOpen(&(ipDSC->device->hwi),                ipDSC->device->drvdesc.dnDevNode, ipDSC->device->pwfx,                (DWORD_PTR)DSOUND_capture_callback, (DWORD)ipDSC->device, flags));            if (err != DS_OK) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?