📄 capture.c
字号:
/* DirectSoundCapture
*
* Copyright 1998 Marcus Meissner
* Copyright 1998 Rob Riggs
* Copyright 2000-2001 TransGaming Technologies, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* TODO:
* Implement FX support.
* Implement both IDirectSoundCaptureBuffer and IDirectSoundCaptureBuffer8
* Make DirectSoundCaptureCreate and DirectSoundCaptureCreate8 behave differently
*/
#include <stdarg.h>
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "mmsystem.h"
#include "mmddk.h"
#include "winreg.h"
#include "winternl.h"
#include "winnls.h"
#include "wine/debug.h"
#include "dsound.h"
#include "dsdriver.h"
#include "dsound_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(
LPDIRECTSOUNDCAPTURE iface,
LPCGUID lpcGUID );
static ULONG WINAPI IDirectSoundCaptureImpl_Release(
LPDIRECTSOUNDCAPTURE iface );
static ULONG WINAPI IDirectSoundCaptureBufferImpl_Release(
LPDIRECTSOUNDCAPTUREBUFFER8 iface );
static HRESULT DSOUND_CreateDirectSoundCaptureBuffer(
IDirectSoundCaptureImpl *ipDSC,
LPCDSCBUFFERDESC lpcDSCBufferDesc,
LPVOID* ppobj );
static const IDirectSoundCaptureVtbl dscvt;
static const IDirectSoundCaptureBuffer8Vtbl dscbvt;
DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS];
static const char * captureStateString[] = {
"STATE_STOPPED",
"STATE_STARTING",
"STATE_CAPTURING",
"STATE_STOPPING"
};
HRESULT WINAPI IDirectSoundCaptureImpl_Create(
LPDIRECTSOUNDCAPTURE8 * ppDSC)
{
IDirectSoundCaptureImpl *pDSC;
TRACE("(%p)\n", ppDSC);
/* Allocate memory */
pDSC = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundCaptureImpl));
if (pDSC == NULL) {
WARN("out of memory\n");
*ppDSC = NULL;
return DSERR_OUTOFMEMORY;
}
pDSC->lpVtbl = &dscvt;
pDSC->ref = 0;
pDSC->device = NULL;
*ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC;
return DS_OK;
}
HRESULT WINAPI DSOUND_CaptureCreate(
LPDIRECTSOUNDCAPTURE *ppDSC,
IUnknown *pUnkOuter)
{
LPDIRECTSOUNDCAPTURE pDSC;
HRESULT hr;
TRACE("(%p,%p)\n",ppDSC,pUnkOuter);
/* Get dsound configuration */
setup_dsound_options();
hr = IDirectSoundCaptureImpl_Create(&pDSC);
if (hr == DS_OK) {
IDirectSoundCapture_AddRef(pDSC);
*ppDSC = pDSC;
} else {
WARN("IDirectSoundCaptureImpl_Create failed\n");
*ppDSC = 0;
}
return hr;
}
HRESULT WINAPI DSOUND_CaptureCreate8(
LPDIRECTSOUNDCAPTURE8 *ppDSC8,
IUnknown *pUnkOuter)
{
LPDIRECTSOUNDCAPTURE8 pDSC8;
HRESULT hr;
TRACE("(%p,%p)\n",ppDSC8,pUnkOuter);
/* Get dsound configuration */
setup_dsound_options();
hr = IDirectSoundCaptureImpl_Create(&pDSC8);
if (hr == DS_OK) {
IDirectSoundCapture_AddRef(pDSC8);
*ppDSC8 = pDSC8;
} else {
WARN("IDirectSoundCaptureImpl_Create failed\n");
*ppDSC8 = 0;
}
return hr;
}
/***************************************************************************
* DirectSoundCaptureCreate [DSOUND.6]
*
* Create and initialize a DirectSoundCapture interface.
*
* PARAMS
* lpcGUID [I] Address of the GUID that identifies the sound capture device.
* lplpDSC [O] Address of a variable to receive the interface pointer.
* pUnkOuter [I] Must be NULL.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
* DSERR_OUTOFMEMORY
*
* NOTES
* lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
* or NULL for the default device or DSDEVID_DefaultCapture or
* DSDEVID_DefaultVoiceCapture.
*
* DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
*/
HRESULT WINAPI DirectSoundCaptureCreate(
LPCGUID lpcGUID,
LPDIRECTSOUNDCAPTURE *ppDSC,
LPUNKNOWN pUnkOuter)
{
HRESULT hr;
LPDIRECTSOUNDCAPTURE pDSC;
TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC, pUnkOuter);
if (ppDSC == NULL) {
WARN("invalid parameter: ppDSC == NULL\n");
return DSERR_INVALIDPARAM;
}
if (pUnkOuter) {
WARN("invalid parameter: pUnkOuter != NULL\n");
*ppDSC = NULL;
return DSERR_NOAGGREGATION;
}
hr = DSOUND_CaptureCreate(&pDSC, (IUnknown *)pUnkOuter);
if (hr == DS_OK) {
hr = IDirectSoundCapture_Initialize(pDSC, lpcGUID);
if (hr != DS_OK) {
IDirectSoundCapture_Release(pDSC);
pDSC = 0;
}
}
*ppDSC = pDSC;
return hr;
}
/***************************************************************************
* DirectSoundCaptureCreate8 [DSOUND.12]
*
* Create and initialize a DirectSoundCapture interface.
*
* PARAMS
* lpcGUID [I] Address of the GUID that identifies the sound capture device.
* lplpDSC [O] Address of a variable to receive the interface pointer.
* pUnkOuter [I] Must be NULL.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
* DSERR_OUTOFMEMORY
*
* NOTES
* lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
* or NULL for the default device or DSDEVID_DefaultCapture or
* DSDEVID_DefaultVoiceCapture.
*
* DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
*/
HRESULT WINAPI DirectSoundCaptureCreate8(
LPCGUID lpcGUID,
LPDIRECTSOUNDCAPTURE8 *ppDSC8,
LPUNKNOWN pUnkOuter)
{
HRESULT hr;
LPDIRECTSOUNDCAPTURE8 pDSC8;
TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC8, pUnkOuter);
if (ppDSC8 == NULL) {
WARN("invalid parameter: ppDSC8 == NULL\n");
return DSERR_INVALIDPARAM;
}
if (pUnkOuter) {
WARN("invalid parameter: pUnkOuter != NULL\n");
*ppDSC8 = NULL;
return DSERR_NOAGGREGATION;
}
hr = DSOUND_CaptureCreate8(&pDSC8, (IUnknown *)pUnkOuter);
if (hr == DS_OK) {
hr = IDirectSoundCapture_Initialize(pDSC8, lpcGUID);
if (hr != DS_OK) {
IDirectSoundCapture_Release(pDSC8);
pDSC8 = 0;
}
}
*ppDSC8 = pDSC8;
return hr;
}
static HRESULT DirectSoundCaptureDevice_Create(
DirectSoundCaptureDevice ** ppDevice)
{
DirectSoundCaptureDevice * device;
TRACE("(%p)\n", ppDevice);
/* Allocate memory */
device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectSoundCaptureDevice));
if (device == NULL) {
WARN("out of memory\n");
return DSERR_OUTOFMEMORY;
}
device->ref = 1;
device->state = STATE_STOPPED;
InitializeCriticalSection( &(device->lock) );
device->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSCAPTURE_lock";
*ppDevice = device;
return DS_OK;
}
/***************************************************************************
* DirectSoundCaptureEnumerateA [DSOUND.7]
*
* Enumerate all DirectSound drivers installed in the system.
*
* PARAMS
* lpDSEnumCallback [I] Address of callback function.
* lpContext [I] Address of user defined context passed to callback function.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_INVALIDPARAM
*/
HRESULT WINAPI
DirectSoundCaptureEnumerateA(
LPDSENUMCALLBACKA lpDSEnumCallback,
LPVOID lpContext)
{
unsigned devs, wid;
DSDRIVERDESC desc;
GUID guid;
int err;
TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
if (lpDSEnumCallback == NULL) {
WARN("invalid parameter: lpDSEnumCallback == NULL\n");
return DSERR_INVALIDPARAM;
}
devs = waveInGetNumDevs();
if (devs > 0) {
if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
for (wid = 0; wid < devs; ++wid) {
if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
"Primary Sound Capture Driver",desc.szDrvname,lpContext);
if (lpDSEnumCallback(NULL, "Primary Sound Capture Driver", desc.szDrvname, lpContext) == FALSE)
return DS_OK;
}
}
}
}
}
for (wid = 0; wid < devs; ++wid) {
err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
if (lpDSEnumCallback(&DSOUND_capture_guids[wid], desc.szDesc, desc.szDrvname, lpContext) == FALSE)
return DS_OK;
}
}
return DS_OK;
}
/***************************************************************************
* DirectSoundCaptureEnumerateW [DSOUND.8]
*
* Enumerate all DirectSound drivers installed in the system.
*
* PARAMS
* lpDSEnumCallback [I] Address of callback function.
* lpContext [I] Address of user defined context passed to callback function.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_INVALIDPARAM
*/
HRESULT WINAPI
DirectSoundCaptureEnumerateW(
LPDSENUMCALLBACKW lpDSEnumCallback,
LPVOID lpContext)
{
unsigned devs, wid;
DSDRIVERDESC desc;
GUID guid;
int err;
WCHAR wDesc[MAXPNAMELEN];
WCHAR wName[MAXPNAMELEN];
TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
if (lpDSEnumCallback == NULL) {
WARN("invalid parameter: lpDSEnumCallback == NULL\n");
return DSERR_INVALIDPARAM;
}
devs = waveInGetNumDevs();
if (devs > 0) {
if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
for (wid = 0; wid < devs; ++wid) {
if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
"Primary Sound Capture Driver",desc.szDrvname,lpContext);
MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
wDesc, sizeof(wDesc)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
wName, sizeof(wName)/sizeof(WCHAR) );
if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
return DS_OK;
}
}
}
}
}
for (wid = 0; wid < devs; ++wid) {
err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
wDesc, sizeof(wDesc)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
wName, sizeof(wName)/sizeof(WCHAR) );
if (lpDSEnumCallback((LPGUID)&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE)
return DS_OK;
}
}
return DS_OK;
}
static void CALLBACK
DSOUND_capture_callback(
HWAVEIN hwi,
UINT msg,
DWORD dwUser,
DWORD dw1,
DWORD dw2 )
{
DirectSoundCaptureDevice * This = (DirectSoundCaptureDevice*)dwUser;
TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi,msg,
msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
if (msg == MM_WIM_DATA) {
LPWAVEHDR pHdr = (LPWAVEHDR)dw1;
EnterCriticalSection( &(This->lock) );
TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
captureStateString[This->state],This->index);
if (This->state != STATE_STOPPED) {
int index = This->index;
if (This->state == STATE_STARTING) {
This->read_position = pHdr->dwBytesRecorded;
This->state = STATE_CAPTURING;
}
if (This->capture_buffer->nrofnotifies)
SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
This->index = (This->index + 1) % This->nrofpwaves;
if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
TRACE("end of buffer\n");
This->state = STATE_STOPPED;
} else {
if (This->state == STATE_CAPTURING) {
waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
} else if (This->state == STATE_STOPPING) {
TRACE("stopping\n");
This->state = STATE_STOPPED;
}
}
}
TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
captureStateString[This->state],This->index);
LeaveCriticalSection( &(This->lock) );
}
TRACE("completed\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -