771 lines
30 KiB
C
771 lines
30 KiB
C
/*
|
|
* Unit tests for capture functions
|
|
*
|
|
* Copyright (c) 2002 Francois Gouget
|
|
* Copyright (c) 2003 Robert Reif
|
|
*
|
|
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#define COBJMACROS
|
|
#include <stdio.h>
|
|
#include "initguid.h"
|
|
#include "windows.h"
|
|
#include "wine/test.h"
|
|
#include "mmsystem.h"
|
|
#include "dsound.h"
|
|
#include "dsconf.h"
|
|
|
|
#include "dsound_test.h"
|
|
|
|
#define TIMESTAMP_NOTIFICATIONS 5
|
|
#define TOTAL_NOTIFICATIONS (TIMESTAMP_NOTIFICATIONS + 1)
|
|
|
|
static const char * get_format_str(WORD format)
|
|
{
|
|
static char msg[32];
|
|
#define WAVE_FORMAT(f) case f: return #f
|
|
switch (format) {
|
|
WAVE_FORMAT(WAVE_FORMAT_PCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_IBM_CVSD);
|
|
WAVE_FORMAT(WAVE_FORMAT_ALAW);
|
|
WAVE_FORMAT(WAVE_FORMAT_MULAW);
|
|
WAVE_FORMAT(WAVE_FORMAT_OKI_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_IMA_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_MEDIASPACE_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_SIERRA_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_G723_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_DIGISTD);
|
|
WAVE_FORMAT(WAVE_FORMAT_DIGIFIX);
|
|
WAVE_FORMAT(WAVE_FORMAT_DIALOGIC_OKI_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_YAMAHA_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_SONARC);
|
|
WAVE_FORMAT(WAVE_FORMAT_DSPGROUP_TRUESPEECH);
|
|
WAVE_FORMAT(WAVE_FORMAT_ECHOSC1);
|
|
WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF36);
|
|
WAVE_FORMAT(WAVE_FORMAT_APTX);
|
|
WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF10);
|
|
WAVE_FORMAT(WAVE_FORMAT_DOLBY_AC2);
|
|
WAVE_FORMAT(WAVE_FORMAT_GSM610);
|
|
WAVE_FORMAT(WAVE_FORMAT_ANTEX_ADPCME);
|
|
WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_VQLPC);
|
|
WAVE_FORMAT(WAVE_FORMAT_DIGIREAL);
|
|
WAVE_FORMAT(WAVE_FORMAT_DIGIADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_CR10);
|
|
WAVE_FORMAT(WAVE_FORMAT_NMS_VBXADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_G721_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_MPEG);
|
|
WAVE_FORMAT(WAVE_FORMAT_MPEGLAYER3);
|
|
WAVE_FORMAT(WAVE_FORMAT_CREATIVE_ADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH8);
|
|
WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH10);
|
|
WAVE_FORMAT(WAVE_FORMAT_FM_TOWNS_SND);
|
|
WAVE_FORMAT(WAVE_FORMAT_OLIGSM);
|
|
WAVE_FORMAT(WAVE_FORMAT_OLIADPCM);
|
|
WAVE_FORMAT(WAVE_FORMAT_OLICELP);
|
|
WAVE_FORMAT(WAVE_FORMAT_OLISBC);
|
|
WAVE_FORMAT(WAVE_FORMAT_OLIOPR);
|
|
WAVE_FORMAT(WAVE_FORMAT_DEVELOPMENT);
|
|
WAVE_FORMAT(WAVE_FORMAT_EXTENSIBLE);
|
|
}
|
|
#undef WAVE_FORMAT
|
|
sprintf(msg, "Unknown(0x%04x)", format);
|
|
return msg;
|
|
}
|
|
|
|
const char * format_string(const WAVEFORMATEX* wfx)
|
|
{
|
|
static char str[64];
|
|
|
|
sprintf(str, "%5dx%2dx%d %s",
|
|
wfx->nSamplesPerSec, wfx->wBitsPerSample, wfx->nChannels,
|
|
get_format_str(wfx->wFormatTag));
|
|
|
|
return str;
|
|
}
|
|
|
|
static void IDirectSoundCapture_test(LPDIRECTSOUNDCAPTURE dsco,
|
|
BOOL initialized, LPCGUID lpGuid)
|
|
{
|
|
HRESULT rc;
|
|
DSCCAPS dsccaps;
|
|
int ref;
|
|
IUnknown * unknown;
|
|
IDirectSoundCapture * dsc;
|
|
|
|
/* Try to Query for objects */
|
|
rc=IDirectSoundCapture_QueryInterface(dsco, &IID_IUnknown,
|
|
(LPVOID*)&unknown);
|
|
ok(rc==DS_OK, "IDirectSoundCapture_QueryInterface(IID_IUnknown) "
|
|
"failed: %08x\n", rc);
|
|
if (rc==DS_OK)
|
|
IUnknown_Release(unknown);
|
|
|
|
rc=IDirectSoundCapture_QueryInterface(dsco, &IID_IDirectSoundCapture,
|
|
(LPVOID*)&dsc);
|
|
ok(rc==DS_OK, "IDirectSoundCapture_QueryInterface(IID_IDirectSoundCapture) "
|
|
"failed: %08x\n", rc);
|
|
if (rc==DS_OK)
|
|
IDirectSoundCapture_Release(dsc);
|
|
|
|
if (initialized == FALSE) {
|
|
/* try uninitialized object */
|
|
rc=IDirectSoundCapture_GetCaps(dsco,0);
|
|
ok(rc==DSERR_UNINITIALIZED||rc==E_INVALIDARG,
|
|
"IDirectSoundCapture_GetCaps(NULL) should have returned "
|
|
"DSERR_UNINITIALIZED or E_INVALIDARG, returned: %08x\n", rc);
|
|
|
|
rc=IDirectSoundCapture_GetCaps(dsco, &dsccaps);
|
|
ok(rc==DSERR_UNINITIALIZED,"IDirectSoundCapture_GetCaps() "
|
|
"should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
|
|
|
|
rc=IDirectSoundCapture_Initialize(dsco, lpGuid);
|
|
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||
|
|
rc==E_FAIL||rc==E_INVALIDARG,
|
|
"IDirectSoundCapture_Initialize() failed: %08x\n", rc);
|
|
if (rc==DSERR_NODRIVER||rc==E_INVALIDARG) {
|
|
trace(" No Driver\n");
|
|
goto EXIT;
|
|
} else if (rc==E_FAIL) {
|
|
trace(" No Device\n");
|
|
goto EXIT;
|
|
} else if (rc==DSERR_ALLOCATED) {
|
|
trace(" Already In Use\n");
|
|
goto EXIT;
|
|
}
|
|
}
|
|
|
|
rc=IDirectSoundCapture_Initialize(dsco, lpGuid);
|
|
ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSoundCapture_Initialize() "
|
|
"should have returned DSERR_ALREADYINITIALIZED: %08x\n", rc);
|
|
|
|
/* DSOUND: Error: Invalid caps buffer */
|
|
rc=IDirectSoundCapture_GetCaps(dsco, 0);
|
|
ok(rc==DSERR_INVALIDPARAM, "IDirectSoundCapture_GetCaps(NULL) "
|
|
"should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
|
|
|
|
ZeroMemory(&dsccaps, sizeof(dsccaps));
|
|
|
|
/* DSOUND: Error: Invalid caps buffer */
|
|
rc=IDirectSoundCapture_GetCaps(dsco, &dsccaps);
|
|
ok(rc==DSERR_INVALIDPARAM, "IDirectSound_GetCaps() "
|
|
"should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
|
|
|
|
dsccaps.dwSize=sizeof(dsccaps);
|
|
|
|
/* DSOUND: Running on a certified driver */
|
|
rc=IDirectSoundCapture_GetCaps(dsco, &dsccaps);
|
|
ok(rc==DS_OK, "IDirectSoundCapture_GetCaps() failed: %08x\n", rc);
|
|
|
|
EXIT:
|
|
ref=IDirectSoundCapture_Release(dsco);
|
|
ok(ref==0, "IDirectSoundCapture_Release() has %d references, "
|
|
"should have 0\n", ref);
|
|
}
|
|
|
|
static void test_capture(void)
|
|
{
|
|
HRESULT rc;
|
|
LPDIRECTSOUNDCAPTURE dsco=NULL;
|
|
LPCLASSFACTORY cf=NULL;
|
|
|
|
trace("Testing IDirectSoundCapture\n");
|
|
|
|
rc=CoGetClassObject(&CLSID_DirectSoundCapture, CLSCTX_INPROC_SERVER, NULL,
|
|
&IID_IClassFactory, (void**)&cf);
|
|
ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSoundCapture, IID_IClassFactory) "
|
|
"failed: %08x\n", rc);
|
|
|
|
rc=CoGetClassObject(&CLSID_DirectSoundCapture, CLSCTX_INPROC_SERVER, NULL,
|
|
&IID_IUnknown, (void**)&cf);
|
|
ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSoundCapture, IID_IUnknown) "
|
|
"failed: %08x\n", rc);
|
|
|
|
/* try the COM class factory method of creation with no device specified */
|
|
rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
|
|
&IID_IDirectSoundCapture, (void**)&dsco);
|
|
ok(rc==S_OK||rc==REGDB_E_CLASSNOTREG,"CoCreateInstance(CLSID_DirectSoundCapture) failed: %08x\n", rc);
|
|
if (rc==REGDB_E_CLASSNOTREG) {
|
|
trace(" Class Not Registered\n");
|
|
return;
|
|
}
|
|
if (dsco)
|
|
IDirectSoundCapture_test(dsco, FALSE, NULL);
|
|
|
|
/* try the COM class factory method of creation with default capture
|
|
* device specified */
|
|
rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
|
|
&IID_IDirectSoundCapture, (void**)&dsco);
|
|
ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSoundCapture) failed: %08x\n", rc);
|
|
if (dsco)
|
|
IDirectSoundCapture_test(dsco, FALSE, &DSDEVID_DefaultCapture);
|
|
|
|
/* try the COM class factory method of creation with default voice
|
|
* capture device specified */
|
|
rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
|
|
&IID_IDirectSoundCapture, (void**)&dsco);
|
|
ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSoundCapture) failed: %08x\n", rc);
|
|
if (dsco)
|
|
IDirectSoundCapture_test(dsco, FALSE, &DSDEVID_DefaultVoiceCapture);
|
|
|
|
/* try the COM class factory method of creation with a bad
|
|
* IID specified */
|
|
rc=CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
|
|
&CLSID_DirectSoundPrivate, (void**)&dsco);
|
|
ok(rc==E_NOINTERFACE,
|
|
"CoCreateInstance(CLSID_DirectSoundCapture,CLSID_DirectSoundPrivate) "
|
|
"should have failed: %08x\n",rc);
|
|
|
|
/* try with no device specified */
|
|
rc = DirectSoundCaptureCreate(NULL, &dsco, NULL);
|
|
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
|
|
"DirectSoundCaptureCreate(NULL) failed: %08x\n",rc);
|
|
if (rc==S_OK && dsco)
|
|
IDirectSoundCapture_test(dsco, TRUE, NULL);
|
|
|
|
/* try with default capture device specified */
|
|
rc = DirectSoundCaptureCreate(&DSDEVID_DefaultCapture, &dsco, NULL);
|
|
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
|
|
"DirectSoundCaptureCreate(DSDEVID_DefaultCapture) failed: %08x\n", rc);
|
|
if (rc==DS_OK && dsco)
|
|
IDirectSoundCapture_test(dsco, TRUE, NULL);
|
|
|
|
/* try with default voice capture device specified */
|
|
rc = DirectSoundCaptureCreate(&DSDEVID_DefaultVoiceCapture, &dsco, NULL);
|
|
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
|
|
"DirectSoundCaptureCreate(DSDEVID_DefaultVoiceCapture) failed: %08x\n", rc);
|
|
if (rc==DS_OK && dsco)
|
|
IDirectSoundCapture_test(dsco, TRUE, NULL);
|
|
|
|
/* try with a bad device specified */
|
|
rc = DirectSoundCaptureCreate(&DSDEVID_DefaultVoicePlayback, &dsco, NULL);
|
|
ok(rc==DSERR_NODRIVER,
|
|
"DirectSoundCaptureCreate(DSDEVID_DefaultVoicePlatback) "
|
|
"should have failed: %08x\n",rc);
|
|
if (rc==DS_OK && dsco)
|
|
IDirectSoundCapture_Release(dsco);
|
|
}
|
|
|
|
typedef struct {
|
|
char* wave;
|
|
DWORD wave_len;
|
|
|
|
LPDIRECTSOUNDCAPTUREBUFFER dscbo;
|
|
LPWAVEFORMATEX wfx;
|
|
DSBPOSITIONNOTIFY posnotify[TOTAL_NOTIFICATIONS];
|
|
HANDLE event[TOTAL_NOTIFICATIONS];
|
|
LPDIRECTSOUNDNOTIFY notify;
|
|
|
|
DWORD buffer_size;
|
|
DWORD read;
|
|
DWORD offset;
|
|
DWORD size;
|
|
|
|
DWORD last_pos;
|
|
} capture_state_t;
|
|
|
|
static BOOL capture_buffer_service(capture_state_t* state)
|
|
{
|
|
HRESULT rc;
|
|
LPVOID ptr1,ptr2;
|
|
DWORD len1,len2;
|
|
DWORD capture_pos,read_pos;
|
|
|
|
rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,
|
|
&read_pos);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCurrentPosition() failed: %08x\n", rc);
|
|
if (rc!=DS_OK)
|
|
return FALSE;
|
|
|
|
rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,
|
|
&ptr1,&len1,&ptr2,&len2,0);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Lock() failed: %08x\n", rc);
|
|
if (rc!=DS_OK)
|
|
return FALSE;
|
|
|
|
rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Unlock() failed: %08x\n", rc);
|
|
if (rc!=DS_OK)
|
|
return FALSE;
|
|
|
|
state->offset = (state->offset + state->size) % state->buffer_size;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,
|
|
LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
|
|
{
|
|
HRESULT rc;
|
|
DSCBCAPS dscbcaps;
|
|
WAVEFORMATEX wfx;
|
|
DWORD size,status;
|
|
capture_state_t state;
|
|
int i, ref;
|
|
|
|
/* Private dsound.dll: Error: Invalid caps pointer */
|
|
rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should "
|
|
"have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
|
|
|
|
/* Private dsound.dll: Error: Invalid caps pointer */
|
|
dscbcaps.dwSize=0;
|
|
rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetCaps() should "
|
|
"have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
|
|
|
|
dscbcaps.dwSize=sizeof(dscbcaps);
|
|
rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCaps() failed: %08x\n", rc);
|
|
if (rc==DS_OK && winetest_debug > 1) {
|
|
trace(" Caps: size = %d flags=0x%08x buffer size=%d\n",
|
|
dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
|
|
}
|
|
|
|
/* Query the format size. Note that it may not match sizeof(wfx) */
|
|
/* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must
|
|
* be non-NULL */
|
|
rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetFormat() should "
|
|
"have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
|
|
|
|
size=0;
|
|
rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size);
|
|
ok(rc==DS_OK && size!=0,"IDirectSoundCaptureBuffer_GetFormat() should "
|
|
"have returned the needed size: rc=%08x, size=%d\n", rc,size);
|
|
|
|
rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetFormat() failed: %08x\n", rc);
|
|
if (rc==DS_OK && winetest_debug > 1) {
|
|
trace(" Format: tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
|
|
wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
|
|
wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
|
|
}
|
|
|
|
/* Private dsound.dll: Error: Invalid status pointer */
|
|
rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCaptureBuffer_GetStatus() should "
|
|
"have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
|
|
|
|
rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %08x\n", rc);
|
|
if (rc==DS_OK && winetest_debug > 1) {
|
|
trace(" Status=0x%04x\n",status);
|
|
}
|
|
|
|
ZeroMemory(&state, sizeof(state));
|
|
state.dscbo=dscbo;
|
|
state.wfx=&wfx;
|
|
state.buffer_size = dscbcaps.dwBufferBytes;
|
|
for (i = 0; i < TOTAL_NOTIFICATIONS; i++)
|
|
state.event[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
|
|
state.size = dscbcaps.dwBufferBytes / TIMESTAMP_NOTIFICATIONS;
|
|
|
|
rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify,
|
|
(void **)&(state.notify));
|
|
ok((rc==DS_OK)&&(state.notify!=NULL),
|
|
"IDirectSoundCaptureBuffer_QueryInterface() failed: %08x\n", rc);
|
|
|
|
for (i = 0; i < TIMESTAMP_NOTIFICATIONS; i++) {
|
|
state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
|
|
state.posnotify[i].hEventNotify = state.event[i];
|
|
}
|
|
|
|
state.posnotify[i].dwOffset = DSBPN_OFFSETSTOP;
|
|
state.posnotify[i].hEventNotify = state.event[i];
|
|
|
|
rc = IDirectSoundNotify_SetNotificationPositions(state.notify, TOTAL_NOTIFICATIONS,
|
|
state.posnotify);
|
|
ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions() failed: %08x\n", rc);
|
|
|
|
ref=IDirectSoundNotify_Release(state.notify);
|
|
ok(ref==0,"IDirectSoundNotify_Release(): has %d references, should have "
|
|
"0\n",ref);
|
|
|
|
rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Start() failed: %08x\n", rc);
|
|
|
|
rc=IDirectSoundCaptureBuffer_Start(dscbo,0);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Start() failed: %08x\n", rc);
|
|
|
|
rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %08x\n", rc);
|
|
ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING) || broken(status==DSCBSTATUS_CAPTURING),
|
|
"GetStatus: bad status: %x\n",status);
|
|
|
|
if (record) {
|
|
/* wait for timestamp notifications */
|
|
for (i = 0; i < (TIMESTAMP_NOTIFICATIONS * 2); i++) {
|
|
rc = WaitForMultipleObjects(TOTAL_NOTIFICATIONS, state.event, FALSE, 3000);
|
|
ok(rc == (WAIT_OBJECT_0 + (i % TIMESTAMP_NOTIFICATIONS)),
|
|
"WaitForMultipleObjects failed: 0x%x\n",rc);
|
|
if (rc != (WAIT_OBJECT_0 + (i % TIMESTAMP_NOTIFICATIONS))) {
|
|
ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED),
|
|
"Wrong notification: should be %d, got %d\n",
|
|
i % TIMESTAMP_NOTIFICATIONS, rc - WAIT_OBJECT_0);
|
|
}
|
|
if (!capture_buffer_service(&state))
|
|
break;
|
|
}
|
|
|
|
}
|
|
rc=IDirectSoundCaptureBuffer_Stop(dscbo);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Stop() failed: %08x\n", rc);
|
|
|
|
/* wait for stop notification */
|
|
rc = WaitForSingleObject(state.event[TIMESTAMP_NOTIFICATIONS], 3000);
|
|
ok(rc == WAIT_OBJECT_0, "WaitForSingleObject failed: 0x%x\n", rc);
|
|
|
|
rc=IDirectSoundCaptureBuffer_Stop(dscbo);
|
|
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Stop() failed: %08x\n", rc);
|
|
}
|
|
|
|
static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
|
|
LPCSTR lpcstrModule, LPVOID lpContext)
|
|
{
|
|
HRESULT rc;
|
|
LPDIRECTSOUNDCAPTURE dsco=NULL;
|
|
LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL;
|
|
DSCBUFFERDESC bufdesc;
|
|
WAVEFORMATEX wfx;
|
|
DSCCAPS dsccaps;
|
|
DWORD f;
|
|
int ref;
|
|
|
|
/* Private dsound.dll: Error: Invalid interface buffer */
|
|
trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
|
|
rc = DirectSoundCaptureCreate(lpGuid, NULL, NULL);
|
|
ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate() should have "
|
|
"returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
|
|
|
|
rc = DirectSoundCaptureCreate(lpGuid, &dsco, NULL);
|
|
ok((rc==DS_OK)||(rc==DSERR_NODRIVER)||(rc==E_FAIL)||(rc==DSERR_ALLOCATED),
|
|
"DirectSoundCaptureCreate() failed: %08x\n",rc);
|
|
if (rc!=DS_OK) {
|
|
if (rc==DSERR_NODRIVER)
|
|
trace(" No Driver\n");
|
|
else if (rc==E_FAIL)
|
|
trace(" No Device\n");
|
|
else if (rc==DSERR_ALLOCATED)
|
|
trace(" Already In Use\n");
|
|
goto EXIT;
|
|
}
|
|
|
|
/* Private dsound.dll: Error: Invalid caps buffer */
|
|
rc=IDirectSoundCapture_GetCaps(dsco,NULL);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_GetCaps() should have "
|
|
"returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
|
|
|
|
/* Private dsound.dll: Error: Invalid caps buffer */
|
|
dsccaps.dwSize=0;
|
|
rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_GetCaps() should have "
|
|
"returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
|
|
|
|
dsccaps.dwSize=sizeof(dsccaps);
|
|
rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
|
|
ok(rc==DS_OK,"IDirectSoundCapture_GetCaps() failed: %08x\n", rc);
|
|
if (rc==DS_OK && winetest_debug > 1) {
|
|
trace(" Caps: size=%d flags=0x%08x formats=%05x channels=%d\n",
|
|
dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,
|
|
dsccaps.dwChannels);
|
|
}
|
|
|
|
/* Private dsound.dll: Error: Invalid size */
|
|
/* Private dsound.dll: Error: Invalid capture buffer description */
|
|
ZeroMemory(&bufdesc, sizeof(bufdesc));
|
|
bufdesc.dwSize=0;
|
|
bufdesc.dwFlags=0;
|
|
bufdesc.dwBufferBytes=0;
|
|
bufdesc.dwReserved=0;
|
|
bufdesc.lpwfxFormat=NULL;
|
|
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
|
|
"should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
|
|
if (rc==DS_OK) {
|
|
ref=IDirectSoundCaptureBuffer_Release(dscbo);
|
|
ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
|
|
"should have 0\n",ref);
|
|
}
|
|
|
|
/* Private dsound.dll: Error: Invalid buffer size */
|
|
/* Private dsound.dll: Error: Invalid capture buffer description */
|
|
ZeroMemory(&bufdesc, sizeof(bufdesc));
|
|
bufdesc.dwSize=sizeof(bufdesc);
|
|
bufdesc.dwFlags=0;
|
|
bufdesc.dwBufferBytes=0;
|
|
bufdesc.dwReserved=0;
|
|
bufdesc.lpwfxFormat=NULL;
|
|
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
|
|
"should have returned DSERR_INVALIDPARAM, returned %08x\n", rc);
|
|
if (rc==DS_OK) {
|
|
ref=IDirectSoundCaptureBuffer_Release(dscbo);
|
|
ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
|
|
"should have 0\n",ref);
|
|
}
|
|
|
|
/* Private dsound.dll: Error: Invalid buffer size */
|
|
/* Private dsound.dll: Error: Invalid capture buffer description */
|
|
ZeroMemory(&bufdesc, sizeof(bufdesc));
|
|
ZeroMemory(&wfx, sizeof(wfx));
|
|
bufdesc.dwSize=sizeof(bufdesc);
|
|
bufdesc.dwFlags=0;
|
|
bufdesc.dwBufferBytes=0;
|
|
bufdesc.dwReserved=0;
|
|
bufdesc.lpwfxFormat=&wfx;
|
|
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
|
|
"should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
|
|
if (rc==DS_OK) {
|
|
ref=IDirectSoundCaptureBuffer_Release(dscbo);
|
|
ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
|
|
"should have 0\n",ref);
|
|
}
|
|
|
|
/* Private dsound.dll: Error: Invalid buffer size */
|
|
/* Private dsound.dll: Error: Invalid capture buffer description */
|
|
init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
|
|
ZeroMemory(&bufdesc, sizeof(bufdesc));
|
|
bufdesc.dwSize=sizeof(bufdesc);
|
|
bufdesc.dwFlags=0;
|
|
bufdesc.dwBufferBytes=0;
|
|
bufdesc.dwReserved=0;
|
|
bufdesc.lpwfxFormat=&wfx;
|
|
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
|
|
ok(rc==DSERR_INVALIDPARAM,"IDirectSoundCapture_CreateCaptureBuffer() "
|
|
"should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
|
|
if (rc==DS_OK) {
|
|
ref=IDirectSoundCaptureBuffer_Release(dscbo);
|
|
ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
|
|
"should have 0\n",ref);
|
|
}
|
|
|
|
for (f = 0; f < ARRAY_SIZE(formats); f++) {
|
|
dscbo=NULL;
|
|
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;
|
|
if (winetest_interactive)
|
|
trace(" Testing the capture buffer at %s\n", format_string(&wfx));
|
|
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
|
|
ok(((rc==DS_OK)&&(dscbo!=NULL))
|
|
|| rc==DSERR_BADFORMAT || rc==DSERR_INVALIDCALL || rc==DSERR_NODRIVER
|
|
|| rc==DSERR_ALLOCATED || rc==E_INVALIDARG || rc==E_FAIL,
|
|
"IDirectSoundCapture_CreateCaptureBuffer() failed to create a "
|
|
"%s capture buffer: %08x\n",format_string(&wfx),rc);
|
|
if (rc==DS_OK) {
|
|
test_capture_buffer(dsco, dscbo, winetest_interactive);
|
|
ref=IDirectSoundCaptureBuffer_Release(dscbo);
|
|
ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d references, "
|
|
"should have 0\n",ref);
|
|
} else if (rc==DSERR_BADFORMAT) {
|
|
ok(!(dsccaps.dwFormats & formats[f][3]),
|
|
"IDirectSoundCapture_CreateCaptureBuffer() failed to create a "
|
|
"capture buffer: format listed as supported but using it failed\n");
|
|
if (!(dsccaps.dwFormats & formats[f][3]))
|
|
trace(" Format not supported: %s\n", format_string(&wfx));
|
|
} else if (rc==DSERR_NODRIVER) {
|
|
trace(" No Driver\n");
|
|
} else if (rc==DSERR_ALLOCATED) {
|
|
trace(" Already In Use\n");
|
|
} else if (rc==E_INVALIDARG) { /* try the old version struct */
|
|
DSCBUFFERDESC1 bufdesc1;
|
|
ZeroMemory(&bufdesc1, sizeof(bufdesc1));
|
|
bufdesc1.dwSize=sizeof(bufdesc1);
|
|
bufdesc1.dwFlags=0;
|
|
bufdesc1.dwBufferBytes=wfx.nAvgBytesPerSec;
|
|
bufdesc1.dwReserved=0;
|
|
bufdesc1.lpwfxFormat=&wfx;
|
|
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,
|
|
(DSCBUFFERDESC*)&bufdesc1,&dscbo,NULL);
|
|
ok(rc==DS_OK || broken(rc==DSERR_INVALIDPARAM),
|
|
"IDirectSoundCapture_CreateCaptureBuffer() failed to create a "
|
|
"%s capture buffer: %08x\n",format_string(&wfx), rc);
|
|
if (rc==DSERR_INVALIDPARAM) {
|
|
skip("broken driver\n");
|
|
goto EXIT;
|
|
}
|
|
if (rc==DS_OK) {
|
|
test_capture_buffer(dsco, dscbo, winetest_interactive);
|
|
ref=IDirectSoundCaptureBuffer_Release(dscbo);
|
|
ok(ref==0,"IDirectSoundCaptureBuffer_Release() has %d "
|
|
"references, should have 0\n",ref);
|
|
}
|
|
} else if (rc==E_FAIL) {
|
|
/* WAVE_FORMAT_PCM only allows 8 and 16 bits per sample, so only
|
|
* report a failure if the bits per sample is 8 or 16
|
|
*/
|
|
if (wfx.wBitsPerSample == 8 || wfx.wBitsPerSample == 16)
|
|
ok(FALSE,"Should not fail for 8 or 16 bits per sample\n");
|
|
}
|
|
}
|
|
|
|
/* try a non PCM format */
|
|
if (0)
|
|
{
|
|
/* FIXME: Why is this commented out? */
|
|
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;
|
|
if (winetest_interactive)
|
|
trace(" Testing the capture buffer at %s\n", format_string(&wfx));
|
|
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
|
|
ok((rc==DS_OK)&&(dscbo!=NULL),"IDirectSoundCapture_CreateCaptureBuffer() "
|
|
"failed to create a capture buffer: %08x\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);
|
|
}
|
|
}
|
|
|
|
/* Try an invalid format to test error handling */
|
|
if (0)
|
|
{
|
|
/* FIXME: Remove this test altogether? */
|
|
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;
|
|
if (winetest_interactive)
|
|
trace(" Testing the capture buffer at %s\n", format_string(&wfx));
|
|
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
|
|
ok(rc!=DS_OK,"IDirectSoundCapture_CreateCaptureBuffer() should have failed "
|
|
"at 2 MHz %08x\n",rc);
|
|
}
|
|
|
|
EXIT:
|
|
if (dsco!=NULL) {
|
|
ref=IDirectSoundCapture_Release(dsco);
|
|
ok(ref==0,"IDirectSoundCapture_Release() has %d references, should "
|
|
"have 0\n",ref);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void test_enumerate(void)
|
|
{
|
|
HRESULT rc;
|
|
rc = DirectSoundCaptureEnumerateA(dscenum_callback, NULL);
|
|
ok(rc==DS_OK,"DirectSoundCaptureEnumerateA() failed: %08x\n", rc);
|
|
}
|
|
|
|
static void test_COM(void)
|
|
{
|
|
IDirectSoundCapture *dsc = (IDirectSoundCapture*)0xdeadbeef;
|
|
IDirectSoundCaptureBuffer *buffer = (IDirectSoundCaptureBuffer*)0xdeadbeef;
|
|
IDirectSoundNotify *notify;
|
|
IUnknown *unk;
|
|
DSCBUFFERDESC bufdesc;
|
|
WAVEFORMATEX wfx;
|
|
HRESULT hr;
|
|
ULONG refcount;
|
|
|
|
hr = DirectSoundCaptureCreate(NULL, &dsc, (IUnknown *)0xdeadbeef);
|
|
ok(hr == DSERR_NOAGGREGATION,
|
|
"DirectSoundCaptureCreate failed: %08x, expected DSERR_NOAGGREGATION\n", hr);
|
|
ok(dsc == (IDirectSoundCapture*)0xdeadbeef, "dsc = %p\n", dsc);
|
|
|
|
hr = DirectSoundCaptureCreate(NULL, &dsc, NULL);
|
|
if (hr == DSERR_NODRIVER) {
|
|
skip("No driver\n");
|
|
return;
|
|
}
|
|
ok(hr == DS_OK, "DirectSoundCaptureCreate failed: %08x, expected DS_OK\n", hr);
|
|
|
|
/* Different refcount for IDirectSoundCapture and for IUnknown */
|
|
refcount = IDirectSoundCapture_AddRef(dsc);
|
|
ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
|
|
hr = IDirectSoundCapture_QueryInterface(dsc, &IID_IUnknown, (void**)&unk);
|
|
ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
|
|
refcount = IUnknown_AddRef(unk);
|
|
ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
|
|
IUnknown_Release(unk);
|
|
IUnknown_Release(unk);
|
|
IDirectSoundCapture_Release(dsc);
|
|
|
|
init_format(&wfx, WAVE_FORMAT_PCM, 44100, 16, 1);
|
|
ZeroMemory(&bufdesc, sizeof(bufdesc));
|
|
bufdesc.dwSize = sizeof(bufdesc);
|
|
bufdesc.dwBufferBytes = wfx.nAvgBytesPerSec;
|
|
bufdesc.lpwfxFormat = &wfx;
|
|
|
|
hr = IDirectSoundCapture_CreateCaptureBuffer(dsc, &bufdesc, &buffer, (IUnknown*)0xdeadbeef);
|
|
if (hr == E_INVALIDARG) {
|
|
/* Old DirectX has only the 1st version of the DSCBUFFERDESC struct */
|
|
bufdesc.dwSize = sizeof(DSCBUFFERDESC1);
|
|
hr = IDirectSoundCapture_CreateCaptureBuffer(dsc, &bufdesc, &buffer, (IUnknown*)0xdeadbeef);
|
|
}
|
|
ok(hr == DSERR_NOAGGREGATION,
|
|
"IDirectSoundCapture_CreateCaptureBuffer failed: %08x, expected DSERR_NOAGGREGATION\n", hr);
|
|
ok(buffer == (IDirectSoundCaptureBuffer*)0xdeadbeef || !buffer /* Win2k without DirectX9 */,
|
|
"buffer = %p\n", buffer);
|
|
|
|
hr = IDirectSoundCapture_CreateCaptureBuffer(dsc, &bufdesc, &buffer, NULL);
|
|
ok(hr == DS_OK, "IDirectSoundCapture_CreateCaptureBuffer failed: %08x, expected DS_OK\n", hr);
|
|
|
|
/* IDirectSoundCaptureBuffer and IDirectSoundNotify have separate refcounts */
|
|
IDirectSoundCaptureBuffer_AddRef(buffer);
|
|
refcount = IDirectSoundCaptureBuffer_AddRef(buffer);
|
|
ok(refcount == 3, "IDirectSoundCaptureBuffer refcount is %u, expected 3\n", refcount);
|
|
hr = IDirectSoundCaptureBuffer_QueryInterface(buffer, &IID_IDirectSoundNotify, (void**)¬ify);
|
|
ok(hr == DS_OK, "IDirectSoundCapture_QueryInterface failed: %08x, expected DS_OK\n", hr);
|
|
refcount = IDirectSoundNotify_AddRef(notify);
|
|
ok(refcount == 2, "IDirectSoundNotify refcount is %u, expected 2\n", refcount);
|
|
IDirectSoundCaptureBuffer_AddRef(buffer);
|
|
refcount = IDirectSoundCaptureBuffer_Release(buffer);
|
|
ok(refcount == 3, "IDirectSoundCaptureBuffer refcount is %u, expected 3\n", refcount);
|
|
|
|
/* Release IDirectSoundCaptureBuffer while keeping IDirectSoundNotify alive */
|
|
while (IDirectSoundCaptureBuffer_Release(buffer) > 0);
|
|
refcount = IDirectSoundNotify_AddRef(notify);
|
|
ok(refcount == 3, "IDirectSoundNotify refcount is %u, expected 3\n", refcount);
|
|
refcount = IDirectSoundCaptureBuffer_AddRef(buffer);
|
|
ok(refcount == 1, "IDirectSoundCaptureBuffer refcount is %u, expected 1\n", refcount);
|
|
|
|
while (IDirectSoundNotify_Release(notify) > 0);
|
|
refcount = IDirectSoundCaptureBuffer_Release(buffer);
|
|
ok(refcount == 0, "IDirectSoundCaptureBuffer refcount is %u, expected 0\n", refcount);
|
|
refcount = IDirectSoundCapture_Release(dsc);
|
|
ok(refcount == 0, "IDirectSoundCapture refcount is %u, expected 0\n", refcount);
|
|
}
|
|
|
|
START_TEST(capture)
|
|
{
|
|
CoInitialize(NULL);
|
|
|
|
test_COM();
|
|
test_capture();
|
|
test_enumerate();
|
|
|
|
CoUninitialize();
|
|
}
|