📄 capture.c
字号:
}
static HRESULT WINAPI
IDirectSoundCaptureImpl_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 WINAPI
IDirectSoundCaptureImpl_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 WINAPI
IDirectSoundCaptureImpl_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 WINAPI
IDirectSoundCaptureImpl_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 WINAPI
IDirectSoundCaptureImpl_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 WINAPI
IDirectSoundCaptureImpl_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 HRESULT
DSOUND_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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -