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