⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 capture.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
}

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 + -