Commit 93d3492f authored by Robert Reif's avatar Robert Reif Committed by Alexandre Julliard

Make capture more reliable by submitting all buffers before start.

Added support for non pcm formats. Added more property set support.
parent e5e1844d
......@@ -79,7 +79,7 @@ static ICOM_VTABLE(IDirectSoundCapture) dscvt;
static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt;
static ICOM_VTABLE(IDirectSoundFullDuplex) dsfdvt;
IDirectSoundCaptureImpl* dsound_capture = NULL;
static IDirectSoundCaptureImpl* dsound_capture = NULL;
/***************************************************************************
* DirectSoundCaptureCreate [DSOUND.6]
......@@ -316,6 +316,7 @@ DSOUND_capture_callback(
EnterCriticalSection( &(This->lock) );
TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%ld, old This->index=%d\n",This->state,This->index);
if (This->state != STATE_STOPPED) {
int index = This->index;
if (This->state == STATE_STARTING) {
MMTIME mtime;
mtime.wType = TIME_BYTES;
......@@ -334,8 +335,8 @@ DSOUND_capture_callback(
This->state = STATE_STOPPED;
} else {
if (This->state == STATE_CAPTURING) {
waveInPrepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR));
waveInAddBuffer(hwi, &(This->pwave[This->index]), sizeof(WAVEHDR));
waveInPrepareHeader(hwi,&(This->pwave[index]),sizeof(WAVEHDR));
waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
}
}
}
......@@ -416,6 +417,9 @@ IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
IDsCaptureDriver_Release(This->driver);
}
if (This->pwfx)
HeapFree(GetProcessHeap(), 0, This->pwfx);
DeleteCriticalSection( &(This->lock) );
HeapFree( GetProcessHeap(), 0, This );
dsound_capture = NULL;
......@@ -678,12 +682,13 @@ DSOUND_CreateDirectSoundCaptureBuffer(
wfex->nAvgBytesPerSec, wfex->nBlockAlign,
wfex->wBitsPerSample, wfex->cbSize);
if (wfex->wFormatTag == WAVE_FORMAT_PCM)
memcpy(&(ipDSC->wfx), wfex, sizeof(WAVEFORMATEX));
else {
WARN("non PCM formats not supported\n");
*ppobj = NULL;
return DSERR_BADFORMAT;
if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX));
memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX));
ipDSC->pwfx->cbSize = 0;
} else {
ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize);
memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize);
}
} else {
WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
......@@ -725,7 +730,7 @@ DSOUND_CreateDirectSoundCaptureBuffer(
if (ipDSC->driver) {
err = IDsCaptureDriver_CreateCaptureBuffer(ipDSC->driver,
&(ipDSC->wfx),0,0,&(ipDSC->buflen),&(ipDSC->buffer),(LPVOID*)&(ipDSC->hwbuf));
ipDSC->pwfx,0,0,&(ipDSC->buflen),&(ipDSC->buffer),(LPVOID*)&(ipDSC->hwbuf));
if (err != DS_OK) {
WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
This->dsound->capture_buffer = 0;
......@@ -740,7 +745,7 @@ DSOUND_CreateDirectSoundCaptureBuffer(
if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
flags |= WAVE_DIRECTSOUND;
err = mmErr(waveInOpen(&(ipDSC->hwi),
ipDSC->drvdesc.dnDevNode, &(ipDSC->wfx),
ipDSC->drvdesc.dnDevNode, ipDSC->pwfx,
(DWORD)DSOUND_capture_callback, (DWORD)ipDSC, flags));
if (err != DS_OK) {
WARN("waveInOpen failed\n");
......@@ -1135,16 +1140,16 @@ IDirectSoundCaptureBufferImpl_GetFormat(
return DSERR_INVALIDPARAM;
}
/* FIXME: use real size for extended formats someday */
if (dwSizeAllocated > sizeof(This->dsound->wfx))
dwSizeAllocated = sizeof(This->dsound->wfx);
if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize))
dwSizeAllocated = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
if (lpwfxFormat) { /* NULL is valid (just want size) */
memcpy(lpwfxFormat,&(This->dsound->wfx),dwSizeAllocated);
memcpy(lpwfxFormat, This->dsound->pwfx, dwSizeAllocated);
if (lpdwSizeWritten)
*lpdwSizeWritten = dwSizeAllocated;
} else {
if (lpdwSizeWritten)
*lpdwSizeWritten = sizeof(This->dsound->wfx);
*lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
else {
TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
return DSERR_INVALIDPARAM;
......@@ -1328,6 +1333,7 @@ IDirectSoundCaptureBufferImpl_Start(
unsigned c;
ipDSC->nrofpwaves = This->nrofnotifies;
TRACE("nrofnotifies=%d\n", This->nrofnotifies);
/* prepare headers */
ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,
......@@ -1350,16 +1356,25 @@ IDirectSoundCaptureBufferImpl_Start(
ipDSC->pwave[c].dwLoops = 0;
err = mmErr(waveInPrepareHeader(ipDSC->hwi,
&(ipDSC->pwave[c]),sizeof(WAVEHDR)));
if (err != DS_OK) {
if (err != DS_OK) {
while (c--)
waveInUnprepareHeader(ipDSC->hwi,
&(ipDSC->pwave[c]),sizeof(WAVEHDR));
break;
}
err = mmErr(waveInAddBuffer(ipDSC->hwi,
&(ipDSC->pwave[c]), sizeof(WAVEHDR)));
if (err != DS_OK) {
while (c--)
waveInUnprepareHeader(ipDSC->hwi,
&(ipDSC->pwave[c]),sizeof(WAVEHDR));
break;
}
waveInUnprepareHeader(ipDSC->hwi,
&(ipDSC->pwave[c]),sizeof(WAVEHDR));
break;
}
}
memset(ipDSC->buffer,
(ipDSC->wfx.wBitsPerSample == 16) ? 0 : 128, ipDSC->buflen);
(ipDSC->pwfx->wBitsPerSample == 8) ? 128 : 0, ipDSC->buflen);
} else {
TRACE("no notifiers specified\n");
/* no notifiers specified so just create a single default header */
......@@ -1378,6 +1393,12 @@ IDirectSoundCaptureBufferImpl_Start(
waveInUnprepareHeader(ipDSC->hwi,
&(ipDSC->pwave[0]),sizeof(WAVEHDR));
}
err = mmErr(waveInAddBuffer(ipDSC->hwi,
&(ipDSC->pwave[0]), sizeof(WAVEHDR)));
if (err != DS_OK) {
waveInUnprepareHeader(ipDSC->hwi,
&(ipDSC->pwave[0]),sizeof(WAVEHDR));
}
}
}
......@@ -1385,17 +1406,8 @@ IDirectSoundCaptureBufferImpl_Start(
ipDSC->read_position = 0;
if (err == DS_OK) {
err = mmErr(waveInReset(ipDSC->hwi));
if (err == DS_OK) {
/* add the first buffer to the queue */
err = mmErr(waveInAddBuffer(ipDSC->hwi, &(ipDSC->pwave[0]), sizeof(WAVEHDR)));
if (err == DS_OK) {
/* start filling the first buffer */
err = mmErr(waveInStart(ipDSC->hwi));
} else
WARN("waveInAddBuffer failed\n");
} else
WARN("waveInReset failed\n");
/* start filling the first buffer */
err = mmErr(waveInStart(ipDSC->hwi));
}
}
......@@ -1443,7 +1455,7 @@ IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
/* Wine-only: the driver wants us to reopen the device */
IDsCaptureDriverBuffer_Release(This->dsound->hwbuf);
err = IDsCaptureDriver_CreateCaptureBuffer(This->dsound->driver,
&(This->dsound->wfx),0,0,&(This->dsound->buflen),&(This->dsound->buffer),
This->dsound->pwfx,0,0,&(This->dsound->buflen),&(This->dsound->buffer),
(LPVOID*)&(This->dsound->hwbuf));
if (err != DS_OK) {
WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
......
......@@ -211,8 +211,7 @@ struct IDirectSoundCaptureImpl
DWORD buflen;
DWORD read_position;
/* FIXME: this should be a pointer because it can be bigger */
WAVEFORMATEX wfx;
PWAVEFORMATEX pwfx;
IDirectSoundCaptureBufferImpl* capture_buffer;
DWORD state;
......@@ -400,7 +399,6 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb);
#define DSOUND_FREQSHIFT (14)
extern IDirectSoundImpl* dsound;
extern IDirectSoundCaptureImpl* dsound_capture;
extern HRESULT mmErr(UINT err);
extern void setup_dsound_options(void);
......@@ -597,6 +597,55 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA(
return E_PROP_ID_UNSUPPORTED;
}
}
} else {
BOOL found = FALSE;
ULONG wod;
int wodn;
/* given specific device so try the render devices first */
wodn = waveOutGetNumDevs();
for (wod = 0; wod < wodn; wod++) {
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
if (err == DS_OK) {
if (IsEqualGUID( &ppd->DeviceId, &guid) ) {
DSDRIVERDESC desc;
TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
ppd->WaveDeviceId = wod;
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
if (err == DS_OK) {
PIDSDRIVER drv = NULL;
/* FIXME: this is a memory leak */
CHAR * szDescription = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDesc) + 1);
CHAR * szModule = HeapAlloc(GetProcessHeap(),0,strlen(desc.szDrvName) + 1);
CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,strlen("Interface") + 1);
strcpy(szDescription, desc.szDesc);
strcpy(szModule, desc.szDrvName);
strcpy(szInterface, "Interface");
ppd->Description = szDescription;
ppd->Module = szModule;
ppd->Interface = szInterface;
err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
if (err == DS_OK && drv)
ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
found = TRUE;
break;
} else {
WARN("waveOutMessage failed\n");
return E_PROP_ID_UNSUPPORTED;
}
}
} else {
WARN("waveOutMessage failed\n");
return E_PROP_ID_UNSUPPORTED;
}
}
if (found == FALSE) {
WARN("device not found\n");
return E_PROP_ID_UNSUPPORTED;
}
}
if (pcbReturned) {
......@@ -723,8 +772,54 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW(
}
}
} else {
FIXME("DeviceId=Unknown\n");
return E_PROP_ID_UNSUPPORTED;
BOOL found = FALSE;
ULONG wod;
int wodn;
/* given specific device so try the render devices first */
wodn = waveOutGetNumDevs();
for (wod = 0; wod < wodn; wod++) {
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
if (err == DS_OK) {
if (IsEqualGUID( &ppd->DeviceId, &guid) ) {
DSDRIVERDESC desc;
TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n");
ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER;
ppd->WaveDeviceId = wod;
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&(desc),0));
if (err == DS_OK) {
PIDSDRIVER drv = NULL;
/* FIXME: this is a memory leak */
WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200);
WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200);
WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,0x200);
MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 );
MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1, wModule, 0x100 );
MultiByteToWideChar( CP_ACP, 0, "Interface", -1, wInterface, 0x100 );
ppd->Description = wDescription;
ppd->Module = wModule;
ppd->Interface = wInterface;
err = mmErr(waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0));
if (err == DS_OK && drv)
ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD;
found = TRUE;
break;
} else {
WARN("waveOutMessage failed\n");
return E_PROP_ID_UNSUPPORTED;
}
}
} else {
WARN("waveOutMessage failed\n");
return E_PROP_ID_UNSUPPORTED;
}
}
if (found == FALSE) {
WARN("device not found\n");
return E_PROP_ID_UNSUPPORTED;
}
}
if (pcbReturned) {
......
......@@ -25,11 +25,13 @@
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "wingdi.h"
#include "dsound.h"
#include "mmreg.h"
static const unsigned int formats[][3]={
{ 8000, 8, 1},
......@@ -61,17 +63,32 @@ static const unsigned int formats[][3]={
#define NOTIFICATIONS 5
static void init_format(WAVEFORMATEX* wfx, int rate, int depth, int channels)
static void init_format(WAVEFORMATEX* wfx, int format, int rate, int depth, int channels)
{
wfx->wFormatTag=WAVE_FORMAT_PCM;
wfx->wFormatTag=format;
wfx->nChannels=channels;
wfx->wBitsPerSample=depth;
wfx->nSamplesPerSec=rate;
wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
if (wfx->nBlockAlign==0) /* align compressed formats to byte boundry */
wfx->nBlockAlign=1;
wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nChannels*wfx->wBitsPerSample/8;
wfx->cbSize=0;
}
static char * format_string(WAVEFORMATEX* wfx)
{
static char str[64];
sprintf(str, "%ldx%dx%d %s",
wfx->nSamplesPerSec, wfx->wBitsPerSample, wfx->nChannels,
wfx->wFormatTag == WAVE_FORMAT_PCM ? "PCM" :
wfx->wFormatTag == WAVE_FORMAT_MULAW ? "MULAW" :
wfx->wFormatTag == WAVE_FORMAT_IMA_ADPCM ? "IMA ADPCM" : "Unknown");
return str;
}
typedef struct {
char* wave;
DWORD wave_len;
......@@ -325,7 +342,7 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
/* Private dsound.dll: Error: Invalid buffer size */
/* Private dsound.dll: Error: Invalid capture buffer description */
init_format(&wfx,11025,8,1);
init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=0;
......@@ -341,15 +358,14 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
for (f=0;f<NB_FORMATS;f++) {
dscbo=NULL;
init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],formats[f][2]);
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=0;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
bufdesc.dwReserved=0;
bufdesc.lpwfxFormat=&wfx;
trace(" Testing the capture buffer at %ldx%dx%d\n",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
trace(" Testing the capture buffer at %s\n", format_string(&wfx));
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
ok((rc==DS_OK)&&(dscbo!=NULL),"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc);
if (rc==DS_OK) {
......@@ -359,17 +375,35 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
}
}
/* try a non PCM format */
#if 0
init_format(&wfx,WAVE_FORMAT_MULAW,8000,8,1);
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
bufdesc.dwReserved=0;
bufdesc.lpwfxFormat=&wfx;
trace(" Testing the capture buffer at %s\n", format_string(&wfx));
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
ok((rc==DS_OK)&&(dscbo!=NULL),"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc);
if ((rc==DS_OK)&&(dscbo!=NULL)) {
test_capture_buffer(dsco, dscbo, winetest_interactive);
ref=IDirectSoundCaptureBuffer_Release(dscbo);
ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
}
#endif
/* Try an invalid format to test error handling */
#if 0
init_format(&wfx,2000000,16,2);
init_format(&wfx,WAVE_FORMAT_PCM,2000000,16,2);
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
bufdesc.dwReserved=0;
bufdesc.lpwfxFormat=&wfx;
trace(" Testing the capture buffer at %ldx%dx%d\n",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
trace(" Testing the capture buffer at %s\n", format_string(&wfx));
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
ok(rc!=DS_OK,"CreateCaptureBuffer should have failed at 2 MHz 0x%lx\n",rc);
#endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment