Dsound from win 2004 month 12 or month 11. It is working in windows 2000 in software emulation mode. Tested with quake2 and some other apps. Not tested in ReactOS

svn path=/trunk/; revision=18339
This commit is contained in:
Magnus Olsen 2005-10-08 16:38:07 +00:00
parent ee7df88f58
commit d0bc2f7b1a
28 changed files with 17297 additions and 28 deletions

1562
reactos/lib/dsound/buffer.c Normal file

File diff suppressed because it is too large Load diff

1888
reactos/lib/dsound/capture.c Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,2 +0,0 @@
EXPORTS
DirectSoundCreate@12 @1

View file

@ -0,0 +1,14 @@
1 stdcall DirectSoundCreate(ptr ptr ptr)
2 stdcall DirectSoundEnumerateA(ptr ptr)
3 stdcall DirectSoundEnumerateW(ptr ptr)
4 stdcall -private DllCanUnloadNow() DSOUND_DllCanUnloadNow
5 stdcall -private DllGetClassObject(ptr ptr ptr) DSOUND_DllGetClassObject
6 stdcall DirectSoundCaptureCreate(ptr ptr ptr) DirectSoundCaptureCreate8
7 stdcall DirectSoundCaptureEnumerateA(ptr ptr)
8 stdcall DirectSoundCaptureEnumerateW(ptr ptr)
9 stdcall GetDeviceID(ptr ptr)
10 stdcall DirectSoundFullDuplexCreate(ptr ptr ptr ptr long long ptr ptr ptr ptr)
11 stdcall DirectSoundCreate8(ptr ptr ptr)
12 stdcall DirectSoundCaptureCreate8(ptr ptr ptr)
@ stdcall -private DllRegisterServer() DSOUND_DllRegisterServer
@ stdcall -private DllUnregisterServer() DSOUND_DllUnregisterServer

View file

@ -1,8 +1,33 @@
<module name="dsound" type="win32dll" baseaddress="${BASEADDRESS_DSOUND}" installbase="system32" installname="dsound.dll">
<importlibrary definition="dsound.def" />
<module name="dsound" type="win32dll" baseaddress="${BASEADDRESS_DSOUND}" installbase="system32" installname="dsound.dll" allowwarnings ="true">
<importlibrary definition="dsound.spec.def" />
<include base="dsound">.</include>
<define name="_DISABLE_TIDENTS" />
<include base="ReactOS">include/wine</include>
<define name="__REACTOS__" />
<define name="__USE_W32API" />
<define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define>
<define name="WINVER">0x501</define>
<library>wine</library>
<library>uuid</library>
<library>ntdll</library>
<library>kernel32</library>
<file>dsound.c</file>
<library>user32</library>
<library>advapi32</library>
<library>ole32</library>
<library>winmm</library>
<library>dxguid</library>
<file>buffer.c</file>
<file>capture.c</file>
<file>dsound.c</file>
<file>dsound_main.c</file>
<file>mixer.c</file>
<file>primary.c</file>
<file>propset.c</file>
<file>regsvr.c</file>
<file>sound3d.c</file>
<file>dxroslayer/dxrosdrv_querydsounddesc.c</file>
<file>dxroslayer/dxrosdrv_querydsoundiface.c</file>
<file>dxroslayer/dxroslayer.c</file>
<file>dxroslayer/getguidfromstring.c</file>
<file>dsound.spec</file>
</module>

View file

@ -0,0 +1,699 @@
/* DirectSound
*
* Copyright 1998 Marcus Meissner
* Copyright 1998 Rob Riggs
* Copyright 2000-2002 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
*/
/*
* Most thread locking is complete. There may be a few race
* conditions still lurking.
*
* Tested with a Soundblaster clone, a Gravis UltraSound Classic,
* and a Turtle Beach Tropez+.
*
* TODO:
* Implement SetCooperativeLevel properly (need to address focus issues)
* Implement DirectSound3DBuffers (stubs in place)
* Use hardware 3D support if available
* Add critical section locking inside Release and AddRef methods
* Handle static buffers - put those in hardware, non-static not in hardware
* Hardware DuplicateSoundBuffer
* Proper volume calculation, and setting volume in HEL primary buffer
* Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define COBJMACROS
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "winternl.h"
#include "mmddk.h"
#include "wine/windef16.h"
#include "wine/winbase16.h"
#include "wine/debug.h"
#include "dsound.h"
#include "dsdriver.h"
#include "dsound_private.h"
#include "dsconf.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
/* these are eligible for tuning... they must be high on slow machines... */
/* some stuff may get more responsive with lower values though... */
#define DS_EMULDRIVER 0 /* some games (Quake 2, UT) refuse to accept
emulated dsound devices. set to 0 ! */
#define DS_HEL_MARGIN 5 /* HEL only: number of waveOut fragments ahead to mix in new buffers
* (keep this close or equal to DS_HEL_QUEUE for best results) */
#define DS_HEL_QUEUE 5 /* HEL only: number of waveOut fragments ahead to queue to driver
* (this will affect HEL sound reliability and latency) */
#define DS_SND_QUEUE_MAX 28 /* max number of fragments to prebuffer */
#define DS_SND_QUEUE_MIN 12 /* min number of fragments to prebuffer */
IDirectSoundImpl* dsound = NULL;
GUID renderer_guids[MAXWAVEDRIVERS];
GUID capture_guids[MAXWAVEDRIVERS];
HRESULT mmErr(UINT err)
{
switch(err) {
case MMSYSERR_NOERROR:
return DS_OK;
case MMSYSERR_ALLOCATED:
return DSERR_ALLOCATED;
case MMSYSERR_ERROR:
case MMSYSERR_INVALHANDLE:
case WAVERR_STILLPLAYING:
return DSERR_GENERIC; /* FIXME */
case MMSYSERR_NODRIVER:
return DSERR_NODRIVER;
case MMSYSERR_NOMEM:
return DSERR_OUTOFMEMORY;
case MMSYSERR_INVALPARAM:
case WAVERR_BADFORMAT:
case WAVERR_UNPREPARED:
return DSERR_INVALIDPARAM;
case MMSYSERR_NOTSUPPORTED:
return DSERR_UNSUPPORTED;
default:
FIXME("Unknown MMSYS error %d\n",err);
return DSERR_GENERIC;
}
}
int ds_emuldriver = DS_EMULDRIVER;
int ds_hel_margin = DS_HEL_MARGIN;
int ds_hel_queue = DS_HEL_QUEUE;
int ds_snd_queue_max = DS_SND_QUEUE_MAX;
int ds_snd_queue_min = DS_SND_QUEUE_MIN;
int ds_hw_accel = DS_HW_ACCEL_FULL;
int ds_default_playback = 0;
int ds_default_capture = 0;
/*
* Get a config key from either the app-specific or the default config
*/
inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
char *buffer, DWORD size )
{
if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, buffer, &size )) return 0;
return RegQueryValueExA( defkey, name, 0, NULL, buffer, &size );
}
/*
* Setup the dsound options.
*/
void setup_dsound_options(void)
{
char buffer[MAX_PATH+1];
HKEY hkey, appkey = 0;
DWORD len;
buffer[MAX_PATH]='\0';
if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\dsound", 0, NULL,
REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ))
{
ERR("Cannot create config registry key\n" );
ExitProcess(1);
}
len = GetModuleFileNameA( 0, buffer, MAX_PATH );
if (len && len < MAX_PATH)
{
HKEY tmpkey;
if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\AppDefaults", &tmpkey ))
{
char appname[MAX_PATH+16];
char *p = strrchr( buffer, '\\' );
if (p!=NULL) {
appname[MAX_PATH]='\0';
strncpy(appname,p+1,MAX_PATH);
strcat(appname,"\\dsound");
TRACE("appname = [%s] \n",appname);
if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
RegCloseKey( tmpkey );
}
}
}
/* get options */
if (!get_config_key( hkey, appkey, "EmulDriver", buffer, MAX_PATH ))
ds_emuldriver = strcmp(buffer, "N");
if (!get_config_key( hkey, appkey, "HELmargin", buffer, MAX_PATH ))
ds_hel_margin = atoi(buffer);
if (!get_config_key( hkey, appkey, "HELqueue", buffer, MAX_PATH ))
ds_hel_queue = atoi(buffer);
if (!get_config_key( hkey, appkey, "SndQueueMax", buffer, MAX_PATH ))
ds_snd_queue_max = atoi(buffer);
if (!get_config_key( hkey, appkey, "SndQueueMin", buffer, MAX_PATH ))
ds_snd_queue_min = atoi(buffer);
if (!get_config_key( hkey, appkey, "HardwareAcceleration", buffer, MAX_PATH )) {
if (strcmp(buffer, "Full") == 0)
ds_hw_accel = DS_HW_ACCEL_FULL;
else if (strcmp(buffer, "Standard") == 0)
ds_hw_accel = DS_HW_ACCEL_STANDARD;
else if (strcmp(buffer, "Basic") == 0)
ds_hw_accel = DS_HW_ACCEL_BASIC;
else if (strcmp(buffer, "Emulation") == 0)
ds_hw_accel = DS_HW_ACCEL_EMULATION;
}
FIXME("dsound are Hardcode to software emulation until we fix it in ros");
ds_hw_accel = DS_HW_ACCEL_EMULATION;
if (!get_config_key( hkey, appkey, "DefaultPlayback", buffer, MAX_PATH ))
ds_default_playback = atoi(buffer);
if (!get_config_key( hkey, appkey, "DefaultCapture", buffer, MAX_PATH ))
ds_default_capture = atoi(buffer);
if (appkey) RegCloseKey( appkey );
RegCloseKey( hkey );
if (ds_emuldriver != DS_EMULDRIVER )
WARN("ds_emuldriver = %d (default=%d)\n",ds_emuldriver, DS_EMULDRIVER);
if (ds_hel_margin != DS_HEL_MARGIN )
WARN("ds_hel_margin = %d (default=%d)\n",ds_hel_margin, DS_HEL_MARGIN );
if (ds_hel_queue != DS_HEL_QUEUE )
WARN("ds_hel_queue = %d (default=%d)\n",ds_hel_queue, DS_HEL_QUEUE );
if (ds_snd_queue_max != DS_SND_QUEUE_MAX)
WARN("ds_snd_queue_max = %d (default=%d)\n",ds_snd_queue_max ,DS_SND_QUEUE_MAX);
if (ds_snd_queue_min != DS_SND_QUEUE_MIN)
WARN("ds_snd_queue_min = %d (default=%d)\n",ds_snd_queue_min ,DS_SND_QUEUE_MIN);
if (ds_hw_accel != DS_HW_ACCEL_FULL)
WARN("ds_hw_accel = %s (default=Full)\n",
ds_hw_accel==DS_HW_ACCEL_FULL ? "Full" :
ds_hw_accel==DS_HW_ACCEL_STANDARD ? "Standard" :
ds_hw_accel==DS_HW_ACCEL_BASIC ? "Basic" :
ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" :
"Unknown");
if (ds_default_playback != 0)
WARN("ds_default_playback = %d (default=0)\n",ds_default_playback);
if (ds_default_capture != 0)
WARN("ds_default_capture = %d (default=0)\n",ds_default_playback);
}
const char * get_device_id(LPCGUID pGuid)
{
if (IsEqualGUID(&DSDEVID_DefaultPlayback, pGuid))
return "DSDEVID_DefaultPlayback";
else if (IsEqualGUID(&DSDEVID_DefaultVoicePlayback, pGuid))
return "DSDEVID_DefaultVoicePlayback";
else if (IsEqualGUID(&DSDEVID_DefaultCapture, pGuid))
return "DSDEVID_DefaultCapture";
else if (IsEqualGUID(&DSDEVID_DefaultVoiceCapture, pGuid))
return "DSDEVID_DefaultVoiceCapture";
return debugstr_guid(pGuid);
}
/***************************************************************************
* GetDeviceID [DSOUND.9]
*
* Retrieves unique identifier of default device specified
*
* PARAMS
* pGuidSrc [I] Address of device GUID.
* pGuidDest [O] Address to receive unique device GUID.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_INVALIDPARAM
*
* NOTES
* pGuidSrc is a valid device GUID or DSDEVID_DefaultPlayback,
* DSDEVID_DefaultCapture, DSDEVID_DefaultVoicePlayback, or
* DSDEVID_DefaultVoiceCapture.
* Returns pGuidSrc if pGuidSrc is a valid device or the device
* GUID for the specified constants.
*/
HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
{
TRACE("(%s,%p)\n", get_device_id(pGuidSrc),pGuidDest);
if ( pGuidSrc == NULL) {
WARN("invalid parameter: pGuidSrc == NULL\n");
return DSERR_INVALIDPARAM;
}
if ( pGuidDest == NULL ) {
WARN("invalid parameter: pGuidDest == NULL\n");
return DSERR_INVALIDPARAM;
}
if ( IsEqualGUID( &DSDEVID_DefaultPlayback, pGuidSrc ) ||
IsEqualGUID( &DSDEVID_DefaultVoicePlayback, pGuidSrc ) ) {
memcpy(pGuidDest, &renderer_guids[ds_default_playback], sizeof(GUID));
TRACE("returns %s\n", get_device_id(pGuidDest));
return DS_OK;
}
if ( IsEqualGUID( &DSDEVID_DefaultCapture, pGuidSrc ) ||
IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
memcpy(pGuidDest, &capture_guids[ds_default_capture], sizeof(GUID));
TRACE("returns %s\n", get_device_id(pGuidDest));
return DS_OK;
}
memcpy(pGuidDest, pGuidSrc, sizeof(GUID));
TRACE("returns %s\n", get_device_id(pGuidDest));
return DS_OK;
}
/***************************************************************************
* DirectSoundEnumerateA [DSOUND.2]
*
* 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 DirectSoundEnumerateA(
LPDSENUMCALLBACKA lpDSEnumCallback,
LPVOID lpContext)
{
unsigned devs, wod;
DSDRIVERDESC desc;
GUID guid;
int err;
TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
lpDSEnumCallback, lpContext);
if (lpDSEnumCallback == NULL) {
WARN("invalid parameter: lpDSEnumCallback == NULL\n");
return DSERR_INVALIDPARAM;
}
devs = waveOutGetNumDevs();
if (devs > 0) {
if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) {
for (wod = 0; wod < devs; ++wod) {
if (IsEqualGUID( &guid, &renderer_guids[wod]) ) {
err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
"Primary Sound Driver",desc.szDrvname,lpContext);
if (lpDSEnumCallback(NULL, "Primary Sound Driver", desc.szDrvname, lpContext) == FALSE)
return DS_OK;
}
}
}
}
}
for (wod = 0; wod < devs; ++wod) {
err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
debugstr_guid(&renderer_guids[wod]),desc.szDesc,desc.szDrvname,lpContext);
if (lpDSEnumCallback(&renderer_guids[wod], desc.szDesc, desc.szDrvname, lpContext) == FALSE)
return DS_OK;
}
}
return DS_OK;
}
/***************************************************************************
* DirectSoundEnumerateW [DSOUND.3]
*
* 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 DirectSoundEnumerateW(
LPDSENUMCALLBACKW lpDSEnumCallback,
LPVOID lpContext )
{
unsigned devs, wod;
DSDRIVERDESC desc;
GUID guid;
int err;
WCHAR wDesc[MAXPNAMELEN];
WCHAR wName[MAXPNAMELEN];
TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
lpDSEnumCallback, lpContext);
if (lpDSEnumCallback == NULL) {
WARN("invalid parameter: lpDSEnumCallback == NULL\n");
return DSERR_INVALIDPARAM;
}
devs = waveOutGetNumDevs();
if (devs > 0) {
if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) {
for (wod = 0; wod < devs; ++wod) {
if (IsEqualGUID( &guid, &renderer_guids[wod] ) ) {
err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
"Primary Sound Driver",desc.szDrvname,lpContext);
MultiByteToWideChar( CP_ACP, 0, "Primary Sound 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 (wod = 0; wod < devs; ++wod) {
err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
debugstr_guid(&renderer_guids[wod]),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(&renderer_guids[wod], wDesc, wName, lpContext) == FALSE)
return DS_OK;
}
}
return DS_OK;
}
/*******************************************************************************
* DirectSound ClassFactory
*/
static HRESULT WINAPI
DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI
DSCF_AddRef(LPCLASSFACTORY iface) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
TRACE("(%p) ref was %ld\n", This, This->ref);
return InterlockedIncrement(&(This->ref));
}
static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
/* static class, won't be freed */
TRACE("(%p) ref was %ld\n", This, This->ref);
return InterlockedDecrement(&(This->ref));
}
static HRESULT WINAPI DSCF_CreateInstance(
LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
if (ppobj == NULL) {
WARN("invalid parameter\n");
return DSERR_INVALIDPARAM;
}
*ppobj = NULL;
if ( IsEqualIID( &IID_IDirectSound, riid ) )
return DSOUND_Create(0,(LPDIRECTSOUND*)ppobj,pOuter);
if ( IsEqualIID( &IID_IDirectSound8, riid ) )
return DSOUND_Create8(0,(LPDIRECTSOUND8*)ppobj,pOuter);
WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
}
static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("(%p)->(%d),stub!\n",This,dolock);
return S_OK;
}
static IClassFactoryVtbl DSCF_Vtbl = {
DSCF_QueryInterface,
DSCF_AddRef,
DSCF_Release,
DSCF_CreateInstance,
DSCF_LockServer
};
static IClassFactoryImpl DSOUND_CF = { &DSCF_Vtbl, 1 };
/*******************************************************************************
* DirectSoundPrivate ClassFactory
*/
static HRESULT WINAPI
DSPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI
DSPCF_AddRef(LPCLASSFACTORY iface) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
TRACE("(%p) ref was %ld\n", This, This->ref);
return InterlockedIncrement(&(This->ref));
}
static ULONG WINAPI
DSPCF_Release(LPCLASSFACTORY iface) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
/* static class, won't be freed */
TRACE("(%p) ref was %ld\n", This, This->ref);
return InterlockedDecrement(&(This->ref));
}
static HRESULT WINAPI
DSPCF_CreateInstance(
LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
if (ppobj == NULL) {
WARN("invalid parameter\n");
return DSERR_INVALIDPARAM;
}
*ppobj = NULL;
if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
return IKsPrivatePropertySetImpl_Create((IKsPrivatePropertySetImpl**)ppobj);
}
WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
}
static HRESULT WINAPI
DSPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
FIXME("(%p)->(%d),stub!\n",This,dolock);
return S_OK;
}
static IClassFactoryVtbl DSPCF_Vtbl = {
DSPCF_QueryInterface,
DSPCF_AddRef,
DSPCF_Release,
DSPCF_CreateInstance,
DSPCF_LockServer
};
static IClassFactoryImpl DSOUND_PRIVATE_CF = { &DSPCF_Vtbl, 1 };
/*******************************************************************************
* DllGetClassObject [DSOUND.5]
* Retrieves class object from a DLL object
*
* NOTES
* Docs say returns STDAPI
*
* PARAMS
* rclsid [I] CLSID for the class object
* riid [I] Reference to identifier of interface for class object
* ppv [O] Address of variable to receive interface pointer for riid
*
* RETURNS
* Success: S_OK
* Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
* E_UNEXPECTED
*/
DWORD WINAPI DSOUND_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv)
{
TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
if (ppv == NULL) {
WARN("invalid parameter\n");
return E_INVALIDARG;
}
*ppv = NULL;
if ( IsEqualCLSID( &CLSID_DirectSound, rclsid ) ||
IsEqualCLSID( &CLSID_DirectSound8, rclsid ) ) {
if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
*ppv = (LPVOID)&DSOUND_CF;
IClassFactory_AddRef((IClassFactory*)*ppv);
return S_OK;
}
WARN("(%s,%s,%p): no interface found.\n",
debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return S_FALSE;
}
if ( IsEqualCLSID( &CLSID_DirectSoundCapture, rclsid ) ||
IsEqualCLSID( &CLSID_DirectSoundCapture8, rclsid ) ) {
if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
*ppv = (LPVOID)&DSOUND_CAPTURE_CF;
IClassFactory_AddRef((IClassFactory*)*ppv);
return S_OK;
}
WARN("(%s,%s,%p): no interface found.\n",
debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return S_FALSE;
}
if ( IsEqualCLSID( &CLSID_DirectSoundFullDuplex, rclsid ) ) {
if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
*ppv = (LPVOID)&DSOUND_FULLDUPLEX_CF;
IClassFactory_AddRef((IClassFactory*)*ppv);
return S_OK;
}
WARN("(%s,%s,%p): no interface found.\n",
debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return S_FALSE;
}
if ( IsEqualCLSID( &CLSID_DirectSoundPrivate, rclsid ) ) {
if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
*ppv = (LPVOID)&DSOUND_PRIVATE_CF;
IClassFactory_AddRef((IClassFactory*)*ppv);
return S_OK;
}
WARN("(%s,%s,%p): no interface found.\n",
debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return S_FALSE;
}
WARN("(%s,%s,%p): no class found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return CLASS_E_CLASSNOTAVAILABLE;
}
/*******************************************************************************
* DllCanUnloadNow [DSOUND.4]
* Determines whether the DLL is in use.
*
* RETURNS
* Success: S_OK
* Failure: S_FALSE
*/
DWORD WINAPI DSOUND_DllCanUnloadNow(void)
{
FIXME("(void): stub\n");
return S_FALSE;
}
#define INIT_GUID(guid, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
guid.Data1 = l; guid.Data2 = w1; guid.Data3 = w2; \
guid.Data4[0] = b1; guid.Data4[1] = b2; guid.Data4[2] = b3; \
guid.Data4[3] = b4; guid.Data4[4] = b5; guid.Data4[5] = b6; \
guid.Data4[6] = b7; guid.Data4[7] = b8;
/***********************************************************************
* DllMain (DSOUND.init)
*/
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
int i;
TRACE("(%p 0x%lx %p)\n", hInstDLL, fdwReason, lpvReserved);
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
TRACE("DLL_PROCESS_ATTACH\n");
for (i = 0; i < MAXWAVEDRIVERS; i++) {
INIT_GUID(renderer_guids[i], 0xbd6dd71a, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
INIT_GUID(capture_guids[i], 0xbd6dd71b, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
}
break;
case DLL_PROCESS_DETACH:
TRACE("DLL_PROCESS_DETACH\n");
break;
case DLL_THREAD_ATTACH:
TRACE("DLL_THREAD_ATTACH\n");
break;
case DLL_THREAD_DETACH:
TRACE("DLL_THREAD_DETACH\n");
break;
default:
TRACE("UNKNOWN REASON\n");
break;
}
return TRUE;
}

View file

@ -0,0 +1,506 @@
/* DirectSound
*
* 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
*/
/* Linux does not support better timing than 10ms */
#define DS_TIME_RES 10 /* Resolution of multimedia timer */
#define DS_TIME_DEL 10 /* Delay of multimedia timer callback, and duration of HEL fragment */
#define DS_HEL_FRAGS 48 /* HEL only: number of waveOut fragments in primary buffer
* (changing this won't help you) */
/* wine spec */
#include "dxroslayer/dxros_layer.h"
/* direct sound hardware acceleration levels */
#define DS_HW_ACCEL_FULL 0 /* default on Windows 98 */
#define DS_HW_ACCEL_STANDARD 1 /* default on Windows 2000 */
#define DS_HW_ACCEL_BASIC 2
#define DS_HW_ACCEL_EMULATION 3
extern int ds_emuldriver;
extern int ds_hel_margin;
extern int ds_hel_queue;
extern int ds_snd_queue_max;
extern int ds_snd_queue_min;
extern int ds_hw_accel;
extern int ds_default_playback;
extern int ds_default_capture;
/*****************************************************************************
* Predeclare the interface implementation structures
*/
typedef struct IDirectSoundImpl IDirectSoundImpl;
typedef struct IDirectSound_IUnknown IDirectSound_IUnknown;
typedef struct IDirectSound_IDirectSound IDirectSound_IDirectSound;
typedef struct IDirectSound8_IUnknown IDirectSound8_IUnknown;
typedef struct IDirectSound8_IDirectSound IDirectSound8_IDirectSound;
typedef struct IDirectSound8_IDirectSound8 IDirectSound8_IDirectSound8;
typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl;
typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl;
typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
typedef struct IDirectSoundFullDuplexImpl IDirectSoundFullDuplexImpl;
typedef struct IDirectSoundNotifyImpl IDirectSoundNotifyImpl;
typedef struct IDirectSoundCaptureNotifyImpl IDirectSoundCaptureNotifyImpl;
typedef struct IDirectSound3DListenerImpl IDirectSound3DListenerImpl;
typedef struct IDirectSound3DBufferImpl IDirectSound3DBufferImpl;
typedef struct IKsBufferPropertySetImpl IKsBufferPropertySetImpl;
typedef struct IKsPrivatePropertySetImpl IKsPrivatePropertySetImpl;
typedef struct PrimaryBufferImpl PrimaryBufferImpl;
typedef struct SecondaryBufferImpl SecondaryBufferImpl;
typedef struct IClassFactoryImpl IClassFactoryImpl;
/*****************************************************************************
* IDirectSound implementation structure
*/
struct IDirectSoundImpl
{
/* IUnknown fields */
IDirectSound8Vtbl *lpVtbl;
DWORD ref;
/* IDirectSoundImpl fields */
GUID guid;
PIDSDRIVER driver;
DSDRIVERDESC drvdesc;
DSDRIVERCAPS drvcaps;
DWORD priolevel;
PWAVEFORMATEX pwfx;
HWAVEOUT hwo;
LPWAVEHDR pwave[DS_HEL_FRAGS];
UINT timerID, pwplay, pwwrite, pwqueue, prebuf, precount;
DWORD fraglen;
PIDSDRIVERBUFFER hwbuf;
LPBYTE buffer;
DWORD writelead, buflen, state, playpos, mixpos;
BOOL need_remix;
int nrofbuffers;
IDirectSoundBufferImpl** buffers;
RTL_RWLOCK buffer_list_lock;
CRITICAL_SECTION mixlock;
PrimaryBufferImpl* primary;
DSBUFFERDESC dsbd;
DWORD speaker_config;
BOOL initialized;
/* DirectSound3DListener fields */
IDirectSound3DListenerImpl* listener;
DS3DLISTENER ds3dl;
BOOL ds3dl_need_recalc;
LPUNKNOWN pUnknown;
LPDIRECTSOUND pDS;
LPDIRECTSOUND8 pDS8;
};
/* reference counted buffer memory for duplicated buffer memory */
typedef struct BufferMemory
{
DWORD ref;
LPBYTE memory;
} BufferMemory;
HRESULT WINAPI IDirectSoundImpl_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND8 * ppds);
HRESULT WINAPI DSOUND_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND *ppDS,
IUnknown *pUnkOuter);
HRESULT WINAPI DSOUND_Create8(
LPCGUID lpcGUID,
LPDIRECTSOUND8 *ppDS,
IUnknown *pUnkOuter);
/*****************************************************************************
* IDirectSound COM components
*/
struct IDirectSound_IUnknown {
IUnknownVtbl *lpVtbl;
DWORD ref;
LPDIRECTSOUND8 pds;
};
HRESULT WINAPI IDirectSound_IUnknown_Create(
LPDIRECTSOUND8 pds,
LPUNKNOWN * ppunk);
struct IDirectSound_IDirectSound {
IDirectSoundVtbl *lpVtbl;
DWORD ref;
LPDIRECTSOUND8 pds;
};
HRESULT WINAPI IDirectSound_IDirectSound_Create(
LPDIRECTSOUND8 pds,
LPDIRECTSOUND * ppds);
/*****************************************************************************
* IDirectSound8 COM components
*/
struct IDirectSound8_IUnknown {
IUnknownVtbl *lpVtbl;
DWORD ref;
LPDIRECTSOUND8 pds;
};
HRESULT WINAPI IDirectSound8_IUnknown_Create(
LPDIRECTSOUND8 pds,
LPUNKNOWN * ppunk);
struct IDirectSound8_IDirectSound {
IDirectSoundVtbl *lpVtbl;
DWORD ref;
LPDIRECTSOUND8 pds;
};
HRESULT WINAPI IDirectSound8_IDirectSound_Create(
LPDIRECTSOUND8 pds,
LPDIRECTSOUND * ppds);
struct IDirectSound8_IDirectSound8 {
IDirectSound8Vtbl *lpVtbl;
DWORD ref;
LPDIRECTSOUND8 pds;
};
HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
LPDIRECTSOUND8 pds,
LPDIRECTSOUND8 * ppds);
/*****************************************************************************
* IDirectSoundBuffer implementation structure
*/
struct IDirectSoundBufferImpl
{
/* FIXME: document */
/* IUnknown fields */
IDirectSoundBuffer8Vtbl *lpVtbl;
DWORD ref;
/* IDirectSoundBufferImpl fields */
SecondaryBufferImpl* dsb;
IDirectSoundImpl* dsound;
CRITICAL_SECTION lock;
PIDSDRIVERBUFFER hwbuf;
PWAVEFORMATEX pwfx;
BufferMemory* buffer;
DWORD playflags,state,leadin;
DWORD playpos,startpos,writelead,buflen;
DWORD nAvgBytesPerSec;
DWORD freq;
DSVOLUMEPAN volpan, cvolpan;
DSBUFFERDESC dsbd;
/* used for frequency conversion (PerfectPitch) */
ULONG freqAdjust, freqAcc;
/* used for intelligent (well, sort of) prebuffering */
DWORD probably_valid_to, last_playpos;
DWORD primary_mixpos, buf_mixpos;
BOOL need_remix;
/* IDirectSoundNotifyImpl fields */
IDirectSoundNotifyImpl* notify;
LPDSBPOSITIONNOTIFY notifies;
int nrofnotifies;
PIDSDRIVERNOTIFY hwnotify;
/* DirectSound3DBuffer fields */
IDirectSound3DBufferImpl* ds3db;
DS3DBUFFER ds3db_ds3db;
LONG ds3db_lVolume;
BOOL ds3db_need_recalc;
/* IKsPropertySet fields */
IKsBufferPropertySetImpl* iks;
};
HRESULT WINAPI IDirectSoundBufferImpl_Create(
IDirectSoundImpl *ds,
IDirectSoundBufferImpl **pdsb,
LPCDSBUFFERDESC dsbd);
HRESULT WINAPI IDirectSoundBufferImpl_Destroy(
IDirectSoundBufferImpl *pdsb);
/*****************************************************************************
* SecondaryBuffer implementation structure
*/
struct SecondaryBufferImpl
{
IDirectSoundBuffer8Vtbl *lpVtbl;
DWORD ref;
IDirectSoundBufferImpl* dsb;
};
HRESULT WINAPI SecondaryBufferImpl_Create(
IDirectSoundBufferImpl *dsb,
SecondaryBufferImpl **pdsb);
HRESULT WINAPI SecondaryBufferImpl_Destroy(
SecondaryBufferImpl *pdsb);
/*****************************************************************************
* PrimaryBuffer implementation structure
*/
struct PrimaryBufferImpl
{
IDirectSoundBuffer8Vtbl *lpVtbl;
DWORD ref;
IDirectSoundImpl* dsound;
};
HRESULT WINAPI PrimaryBufferImpl_Create(
IDirectSoundImpl *ds,
PrimaryBufferImpl **pdsb,
LPCDSBUFFERDESC dsbd);
/*****************************************************************************
* IDirectSoundCapture implementation structure
*/
struct IDirectSoundCaptureImpl
{
/* IUnknown fields */
IDirectSoundCaptureVtbl *lpVtbl;
DWORD ref;
/* IDirectSoundCaptureImpl fields */
GUID guid;
BOOL initialized;
/* DirectSound driver stuff */
PIDSCDRIVER driver;
DSDRIVERDESC drvdesc;
DSCDRIVERCAPS drvcaps;
PIDSCDRIVERBUFFER hwbuf;
/* wave driver info */
HWAVEIN hwi;
/* more stuff */
LPBYTE buffer;
DWORD buflen;
DWORD read_position;
PWAVEFORMATEX pwfx;
IDirectSoundCaptureBufferImpl* capture_buffer;
DWORD state;
LPWAVEHDR pwave;
int nrofpwaves;
int index;
CRITICAL_SECTION lock;
};
/*****************************************************************************
* IDirectSoundCaptureBuffer implementation structure
*/
struct IDirectSoundCaptureBufferImpl
{
/* IUnknown fields */
IDirectSoundCaptureBuffer8Vtbl *lpVtbl;
DWORD ref;
/* IDirectSoundCaptureBufferImpl fields */
IDirectSoundCaptureImpl* dsound;
/* FIXME: don't need this */
LPDSCBUFFERDESC pdscbd;
DWORD flags;
/* IDirectSoundCaptureNotifyImpl fields */
IDirectSoundCaptureNotifyImpl* notify;
LPDSBPOSITIONNOTIFY notifies;
int nrofnotifies;
PIDSDRIVERNOTIFY hwnotify;
};
/*****************************************************************************
* IDirectSoundFullDuplex implementation structure
*/
struct IDirectSoundFullDuplexImpl
{
/* IUnknown fields */
IDirectSoundFullDuplexVtbl *lpVtbl;
DWORD ref;
/* IDirectSoundFullDuplexImpl fields */
CRITICAL_SECTION lock;
};
/*****************************************************************************
* IDirectSoundNotify implementation structure
*/
struct IDirectSoundNotifyImpl
{
/* IUnknown fields */
IDirectSoundNotifyVtbl *lpVtbl;
DWORD ref;
IDirectSoundBufferImpl* dsb;
};
HRESULT WINAPI IDirectSoundNotifyImpl_Create(
IDirectSoundBufferImpl *dsb,
IDirectSoundNotifyImpl **pdsn);
HRESULT WINAPI IDirectSoundNotifyImpl_Destroy(
IDirectSoundNotifyImpl *pdsn);
/*****************************************************************************
* IDirectSoundCaptureNotify implementation structure
*/
struct IDirectSoundCaptureNotifyImpl
{
/* IUnknown fields */
IDirectSoundNotifyVtbl *lpVtbl;
DWORD ref;
IDirectSoundCaptureBufferImpl* dscb;
};
HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create(
IDirectSoundCaptureBufferImpl *dscb,
IDirectSoundCaptureNotifyImpl ** pdscn);
/*****************************************************************************
* IDirectSound3DListener implementation structure
*/
struct IDirectSound3DListenerImpl
{
/* IUnknown fields */
IDirectSound3DListenerVtbl *lpVtbl;
DWORD ref;
/* IDirectSound3DListenerImpl fields */
IDirectSoundImpl* dsound;
};
HRESULT WINAPI IDirectSound3DListenerImpl_Create(
PrimaryBufferImpl *pb,
IDirectSound3DListenerImpl **pdsl);
/*****************************************************************************
* IKsBufferPropertySet implementation structure
*/
struct IKsBufferPropertySetImpl
{
/* IUnknown fields */
IKsPropertySetVtbl *lpVtbl;
DWORD ref;
/* IKsPropertySetImpl fields */
IDirectSoundBufferImpl* dsb;
};
HRESULT WINAPI IKsBufferPropertySetImpl_Create(
IDirectSoundBufferImpl *dsb,
IKsBufferPropertySetImpl **piks);
HRESULT WINAPI IKsBufferPropertySetImpl_Destroy(
IKsBufferPropertySetImpl *piks);
/*****************************************************************************
* IKsPrivatePropertySet implementation structure
*/
struct IKsPrivatePropertySetImpl
{
/* IUnknown fields */
IKsPropertySetVtbl *lpVtbl;
DWORD ref;
};
HRESULT WINAPI IKsPrivatePropertySetImpl_Create(
IKsPrivatePropertySetImpl **piks);
/*****************************************************************************
* IDirectSound3DBuffer implementation structure
*/
struct IDirectSound3DBufferImpl
{
/* IUnknown fields */
IDirectSound3DBufferVtbl *lpVtbl;
DWORD ref;
/* IDirectSound3DBufferImpl fields */
IDirectSoundBufferImpl* dsb;
};
HRESULT WINAPI IDirectSound3DBufferImpl_Create(
IDirectSoundBufferImpl *dsb,
IDirectSound3DBufferImpl **pds3db);
HRESULT WINAPI IDirectSound3DBufferImpl_Destroy(
IDirectSound3DBufferImpl *pds3db);
/*******************************************************************************
* DirectSound ClassFactory implementation structure
*/
struct IClassFactoryImpl
{
/* IUnknown fields */
IClassFactoryVtbl *lpVtbl;
DWORD ref;
};
extern IClassFactoryImpl DSOUND_CAPTURE_CF;
extern IClassFactoryImpl DSOUND_FULLDUPLEX_CF;
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan);
void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan);
void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb);
/* dsound.c */
HRESULT DSOUND_AddBuffer(IDirectSoundImpl * pDS, IDirectSoundBufferImpl * pDSB);
HRESULT DSOUND_RemoveBuffer(IDirectSoundImpl * pDS, IDirectSoundBufferImpl * pDSB);
/* primary.c */
HRESULT DSOUND_PrimaryCreate(IDirectSoundImpl *This);
HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This);
HRESULT DSOUND_PrimaryPlay(IDirectSoundImpl *This);
HRESULT DSOUND_PrimaryStop(IDirectSoundImpl *This);
HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWORD writepos);
/* buffer.c */
DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This,
DWORD state, DWORD pplay, DWORD pwrite, DWORD pmix, DWORD bmix);
/* mixer.c */
void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len);
void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb);
void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos);
void DSOUND_WaveQueue(IDirectSoundImpl *dsound, DWORD mixq);
void DSOUND_PerformMix(IDirectSoundImpl *dsound);
void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
/* sound3d.c */
void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb);
#define STATE_STOPPED 0
#define STATE_STARTING 1
#define STATE_PLAYING 2
#define STATE_CAPTURING 2
#define STATE_STOPPING 3
#define DSOUND_FREQSHIFT (14)
extern IDirectSoundImpl* dsound;
extern GUID renderer_guids[MAXWAVEDRIVERS];
extern GUID capture_guids[MAXWAVEDRIVERS];
extern HRESULT mmErr(UINT err);
extern void setup_dsound_options(void);
extern const char * get_device_id(LPCGUID pGuid);

View file

@ -0,0 +1,62 @@
/*
* 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
*
* ReactOS emulation layer betwin wine and windows api for directx
* This transform wine specfiy api to native reactos/windows api
* wine have done some hack to geting dsound working. But does
* hack does not work on windows or reactos. It need to warp thuse
* api hack to true native api.
*
* this include file really need to be clean up.
*
* copyright 2004 by magnus olsen
*/
#ifdef __REACTOS__
#include <mmsystem.h>
// wine spec
#define MAXWAVEDRIVERS 10
#define MAXMIDIDRIVERS 10
#define MAXAUXDRIVERS 10
#define MAXMCIDRIVERS 32
#define MAXMIXERDRIVERS 10
/* where */
#ifdef RC_INVOKED
#define _HRESULT_TYPEDEF_(x) (x)
#else
#define _HRESULT_TYPEDEF_(x) ((HRESULT)x)
#endif
/* wine own api */
#define DRV_QUERYDSOUNDIFACE (DRV_RESERVED + 20)
#define DRV_QUERYDSOUNDDESC (DRV_RESERVED + 21)
#define WineWaveOutMessage RosWineWaveOutMessage
#define WineWaveInMessage RosWineWaveInMessage
#else
#define WineWaveOutMessage WaveOutMessage
#define WineWaveInMessage WaveInMessage
#endif
/* dxroslayers prototypes */
void dxGetGuidFromString( char *in_str, GUID *guid );
DWORD dxrosdrv_drv_querydsounddesc(int type, HWAVEOUT hwo_out,HWAVEIN hwo_in, PDSDRIVERDESC pDESC);
DWORD dxrosdrv_drv_querydsoundiface(HWAVEIN wDevID, PIDSDRIVER* drv);
DWORD RosWineWineWaveOutMessage(HWAVEOUT hwo, UINT , DWORD_PTR , DWORD_PTR );
DWORD RosWineWineWaveInMessage(HWAVEIN , UINT , DWORD_PTR , DWORD_PTR );

View file

@ -0,0 +1,163 @@
/*
* reactos emulation layer betwin wine and windows api for directx
* get hardware dec
* Copyright 2004 Magnus Olsen
*
* 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:
* soucre clean
* need to rewrite almost everthing so it get all info from the hardware instead
* see todo.rtf
*
* put it in own library that call dxroslayer.a
*
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "winternl.h"
#include "mmddk.h"
#include "wine/windef16.h"
#include "wine/winbase16.h"
#include "wine/debug.h"
#include "dsound.h"
#include "dsdriver.h"
#include "dxros_layer.h"
#include "dsconf.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
DWORD dxrosdrv_drv_querydsounddescss(int type, HWAVEOUT hwo_out,HWAVEIN hwo_in, PDSDRIVERDESC pDESC)
{
WAVEOUTCAPSA ac_play;
WAVEINCAPSA ac_rec;
DWORD msg;
// type 0 = out
// clear data
memset(pDESC,0,sizeof(DSDRIVERDESC));
memset((char *)pDESC->szDrvname,0,255);
if (type==0) memset(&ac_play,0,sizeof(WAVEOUTCAPSA));
else memset(&ac_rec,0,sizeof(WAVEINCAPSA));
// get some data
if (type==0) {
msg = waveOutGetDevCapsA((UINT)hwo_out,&ac_play,sizeof(WAVEOUTCAPSA));
if (ac_play.szPname==NULL) return MMSYSERR_NOTSUPPORTED;
}
else {
msg = waveInGetDevCapsA((UINT)hwo_in,&ac_rec,sizeof(WAVEINCAPSA));
if (ac_rec.szPname==NULL) return MMSYSERR_NOTSUPPORTED;
}
if (msg!=MMSYSERR_NOERROR) return msg;
// setting up value
//pDESC->wReserved = NULL;
if (type==0) {
pDESC->ulDeviceNum = (ULONG)hwo_out;
memcpy((char *)pDESC->szDesc,ac_play.szPname,strlen(ac_play.szPname));
}
else {
pDESC->ulDeviceNum = (ULONG)hwo_in;
memcpy((char *)pDESC->szDesc,ac_rec.szPname,strlen(ac_rec.szPname));
}
// FIXME
/* how to fill these
pDESC->dwFlags |= DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT |
DSDDESC_USESYSTEMMEMORY | DSDDESC_DONTNEEDPRIMARYLOCK |
DSDDESC_DONTNEEDSECONDARYLOCK;
//pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode;
pDESC->wVxdId = 0;
pDESC->wReserved = 0;
pDESC->dwHeapType = DSDHEAP_NOHEAP;
pDESC->pvDirectDrawHeap = NULL;
pDESC->dwMemStartAddress = 0;
pDESC->dwMemEndAddress = 0;
pDESC->dwMemAllocExtra = 0;
pDESC->pvReserved1 = NULL;
pDESC->pvReserved2 = NULL;
*/
pDESC->pvReserved1 = NULL;
pDESC->pvReserved2 = NULL;
// we need to fill it right so we do not need ddraw.dll
pDESC->pvDirectDrawHeap = NULL; // wine dsound does not use ddraw.dll
// need to write dective for it
pDESC->dwHeapType = DSDHEAP_NOHEAP;
// have take the value from wine audio drv
pDESC->dwFlags = DSDDESC_DOMMSYSTEMOPEN |
DSDDESC_DOMMSYSTEMSETFORMAT |
DSDDESC_USESYSTEMMEMORY |
DSDDESC_DONTNEEDPRIMARYLOCK |
DSDDESC_DONTNEEDSECONDARYLOCK;
//WAVEOPENDESC->DevNode need to fig. how to get it from mmdrv
pDESC->dnDevNode = 0; // wine dsound are using this value
// need to fill the rest also
// must contain the audio drv name
// but how to get it ?
//memcpy((char *)pDESC->szDrvname,(char *)&"kx.sys",6);
pDESC->dwMemStartAddress = 0;
pDESC->dwMemAllocExtra = 0;
pDESC->wVxdId = 0;
return MMSYSERR_NOERROR;
}

View file

@ -0,0 +1,72 @@
/*
* reactos emulation layer betwin wine and windows api for directx
*
* Copyright 2004 Magnus Olsen
*
* 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:
* write hardware support for windows nt 4.0 and higher
* put it in own library that call dxroslayer.a
*
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "winternl.h"
#include "mmddk.h"
#include "wine/windef16.h"
#include "wine/winbase16.h"
#include "wine/debug.h"
#include "dsound.h"
#include "dsdriver.h"
#include "dsconf.h"
#include "windows.h"
#include "dxros_layer.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
DWORD dxrosdrv_drv_querydsoundiface(HWAVEIN wDevID, PIDSDRIVER* drv)
{
// no hardware support for dsound NT 4.0 does not support it
// but win 2000/xp drv does support hardware support of direct sound
drv = NULL;
// drv should be fild with hardware pointers see PIDSDRIVER struct
return MMSYSERR_NOERROR;
}

View file

@ -0,0 +1,115 @@
/*
*
* 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
*
* ReactOS emulation layer betwin wine and windows api for directx
* This transform wine specfiy api to native reactos/windows api
* wine have done some hack to geting dsound working. But does
* hack does not work on windows or reactos. It need to warp thuse
* api hack to true native api.
*
* This layer have some weekness
* it does not support hardware accleration of the sound card.
* it need complete implant of it here, and we need also wdm
* in reactos to complete dsound. for monet it is not posibile
* to get all value and fill them. eg the soundcard drv name.
*
* Wine does get almost everthing from there sound drv, then
* pass it thurg winmm, then to dsound. but windows drv does
* not pass this info to the winmm. it send it on wdm instead.
*
* Do rember this dsound is hardcode to software mode only.
* the program will not notice it. it will think it is hardware.
* for the flag never report back it is in software mode.
*
*
* Copyright 2004 Magnus Olsen
*
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "winternl.h"
#include "mmddk.h"
#include "wine/windef16.h"
#include "wine/winbase16.h"
#include "wine/debug.h"
#include "dsound.h"
#include "dsdriver.h"
#include "dxros_layer.h"
#include "dsconf.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
DWORD RosWineWaveOutMessage(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
DWORD msg;
switch (uMsg) {
case DRV_QUERYDSOUNDDESC:
msg = dxrosdrv_drv_querydsounddescss(0, (HWAVEOUT)((ULONG)hwo),(HWAVEIN) 0, (PDSDRIVERDESC) dwParam1);
break;
case DRV_QUERYDSOUNDIFACE:
msg = dxrosdrv_drv_querydsoundiface((HWAVEIN)hwo, (PIDSDRIVER)dwParam1);
break;
default :
msg = waveOutMessage(hwo, uMsg, dwParam1, dwParam2);
break;
}
return msg;
}
DWORD RosWineWaveInMessage(HWAVEIN hwo, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
DWORD msg;
switch (uMsg) {
case DRV_QUERYDSOUNDDESC:
msg = dxrosdrv_drv_querydsounddescss(1, (HWAVEOUT)((ULONG)0),(HWAVEIN)((ULONG)hwo), (PDSDRIVERDESC) dwParam1);
break;
case DRV_QUERYDSOUNDIFACE:
msg = dxrosdrv_drv_querydsoundiface(hwo, (PIDSDRIVER)dwParam1);
break;
default :
msg = waveInMessage(hwo, uMsg, dwParam1, dwParam2);
break;
}
return msg;
}

View file

@ -0,0 +1,176 @@
/*
* ReactOS emulation layer betwin wine and windows api for directx
* convort string to GUID
*
* Copyright 2004 Magnus Olsen
*
* 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:
* soucre clean
* Rewrite so it use unicode instead for asc or find how windows convert it
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "winternl.h"
#include "mmddk.h"
#include "wine/windef16.h"
#include "wine/winbase16.h"
#include "wine/debug.h"
#include "dsound.h"
#include "dsdriver.h"
#include "dxros_layer.h"
#include "dsconf.h"
#include "windows.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
void dxGetGuidFromString( char *in_str, GUID *guid )
{
unsigned long c=0;
int i;
// this string hex converter need to be rewrite or find uhow windows convort a string
// to GUID
for (i=1;i<9;i++)
{
if (in_str[i]>='0' && in_str[i]<='9')
{
c=c * 16 + (in_str[i] - 48);
}
else if (in_str[i]>='A' && in_str[i]<='F')
{
c=c * 16 + (in_str[i] - 55);
}
}
guid->Data1 = c;
c=0;
for (i=9;i<14;i++)
{
if (in_str[i]>='0' && in_str[i]<='9')
{
c=c * 16 + (in_str[i] - 48);
}
else if (in_str[i]>='A' && in_str[i]<='F')
{
c=c * 16 + (in_str[i] - 55);
}
}
guid->Data2 = (short) c;
c=0;
for (i=14;i<19;i++)
{
if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48);
else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55);
}
guid->Data3 = (short) c;
c=0;
for (i=20;i<22;i++)
{
if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48);
else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55);
}
guid->Data4[0] = (BYTE) c;
c=0;
for (i=22;i<24;i++)
{
if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48);
else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55);
}
guid->Data4[1] = (BYTE) c;
c=0;
for (i=25;i<27;i++)
{
if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48);
else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55);
}
guid->Data4[2] = (BYTE) c;
c=0;
for (i=27;i<29;i++)
{
if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48);
else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55);
}
guid->Data4[3] = (BYTE) c;
c=0;
for (i=29;i<31;i++)
{
if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48);
else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55);
}
guid->Data4[4] = (BYTE) c;
c=0;
for (i=31;i<33;i++)
{
if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48);
else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55);
}
guid->Data4[5] = (BYTE) c;
c=0;
for (i=33;i<35;i++)
{
if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48);
else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55);
}
guid->Data4[6] = (BYTE) c;
c=0;
for (i=35;i<37;i++)
{
if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48);
else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55);
}
guid->Data4[7] = (BYTE) c;
c=0;
}

1188
reactos/lib/dsound/mixer.c Normal file

File diff suppressed because it is too large Load diff

1105
reactos/lib/dsound/primary.c Normal file

File diff suppressed because it is too large Load diff

1163
reactos/lib/dsound/propset.c Normal file

File diff suppressed because it is too large Load diff

584
reactos/lib/dsound/regsvr.c Normal file
View file

@ -0,0 +1,584 @@
/*
* self-registerable dll functions for dsound.dll
*
* Copyright (C) 2003 John K. Hohm
*
* 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
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "winerror.h"
#include "mmsystem.h"
#include "dsound.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
/*
* Near the bottom of this file are the exported DllRegisterServer and
* DllUnregisterServer, which make all this worthwhile.
*/
/***********************************************************************
* interface for self-registering
*/
struct regsvr_interface
{
IID const *iid; /* NULL for end of list */
LPCSTR name; /* can be NULL to omit */
IID const *base_iid; /* can be NULL to omit */
int num_methods; /* can be <0 to omit */
CLSID const *ps_clsid; /* can be NULL to omit */
CLSID const *ps_clsid32; /* can be NULL to omit */
};
static HRESULT register_interfaces(struct regsvr_interface const *list);
static HRESULT unregister_interfaces(struct regsvr_interface const *list);
struct regsvr_coclass
{
CLSID const *clsid; /* NULL for end of list */
LPCSTR name; /* can be NULL to omit */
LPCSTR ips; /* can be NULL to omit */
LPCSTR ips32; /* can be NULL to omit */
LPCSTR ips32_tmodel; /* can be NULL to omit */
LPCSTR progid; /* can be NULL to omit */
LPCSTR viprogid; /* can be NULL to omit */
LPCSTR progid_extra; /* can be NULL to omit */
};
static HRESULT register_coclasses(struct regsvr_coclass const *list);
static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
/***********************************************************************
* static string constants
*/
static WCHAR const interface_keyname[10] = {
'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
static WCHAR const base_ifa_keyname[14] = {
'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
'e', 0 };
static WCHAR const num_methods_keyname[11] = {
'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
static WCHAR const ps_clsid_keyname[15] = {
'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
'i', 'd', 0 };
static WCHAR const ps_clsid32_keyname[17] = {
'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
'i', 'd', '3', '2', 0 };
static WCHAR const clsid_keyname[6] = {
'C', 'L', 'S', 'I', 'D', 0 };
static WCHAR const curver_keyname[7] = {
'C', 'u', 'r', 'V', 'e', 'r', 0 };
static WCHAR const ips_keyname[13] = {
'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
0 };
static WCHAR const ips32_keyname[15] = {
'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
'3', '2', 0 };
static WCHAR const progid_keyname[7] = {
'P', 'r', 'o', 'g', 'I', 'D', 0 };
static WCHAR const viprogid_keyname[25] = {
'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
0 };
static char const tmodel_valuename[] = "ThreadingModel";
/***********************************************************************
* static helper functions
*/
static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
WCHAR const *value);
static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
char const *value);
static LONG register_progid(WCHAR const *clsid,
char const *progid, char const *curver_progid,
char const *name, char const *extra);
static LONG recursive_delete_key(HKEY key);
static LONG recursive_delete_keyA(HKEY base, char const *name);
static LONG recursive_delete_keyW(HKEY base, WCHAR const *name);
/***********************************************************************
* register_interfaces
*/
static HRESULT register_interfaces(struct regsvr_interface const *list)
{
LONG res = ERROR_SUCCESS;
HKEY interface_key;
res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
if (res != ERROR_SUCCESS) goto error_return;
for (; res == ERROR_SUCCESS && list->iid; ++list) {
WCHAR buf[39];
HKEY iid_key;
StringFromGUID2(list->iid, buf, 39);
res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
if (res != ERROR_SUCCESS) goto error_close_interface_key;
if (list->name) {
res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
(CONST BYTE*)(list->name),
strlen(list->name) + 1);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
if (list->base_iid) {
register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
if (0 <= list->num_methods) {
static WCHAR const fmt[3] = { '%', 'd', 0 };
HKEY key;
res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &key, NULL);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
wsprintfW(buf, fmt, list->num_methods);
res = RegSetValueExW(key, NULL, 0, REG_SZ,
(CONST BYTE*)buf,
(lstrlenW(buf) + 1) * sizeof(WCHAR));
RegCloseKey(key);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
if (list->ps_clsid) {
register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
if (list->ps_clsid32) {
register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
if (res != ERROR_SUCCESS) goto error_close_iid_key;
}
error_close_iid_key:
RegCloseKey(iid_key);
}
error_close_interface_key:
RegCloseKey(interface_key);
error_return:
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
}
/***********************************************************************
* unregister_interfaces
*/
static HRESULT unregister_interfaces(struct regsvr_interface const *list)
{
LONG res = ERROR_SUCCESS;
HKEY interface_key;
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
KEY_READ | KEY_WRITE, &interface_key);
if (res == ERROR_FILE_NOT_FOUND) return S_OK;
if (res != ERROR_SUCCESS) goto error_return;
for (; res == ERROR_SUCCESS && list->iid; ++list) {
WCHAR buf[39];
StringFromGUID2(list->iid, buf, 39);
res = recursive_delete_keyW(interface_key, buf);
}
RegCloseKey(interface_key);
error_return:
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
}
/***********************************************************************
* register_coclasses
*/
static HRESULT register_coclasses(struct regsvr_coclass const *list)
{
LONG res = ERROR_SUCCESS;
HKEY coclass_key;
res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
if (res != ERROR_SUCCESS) goto error_return;
for (; res == ERROR_SUCCESS && list->clsid; ++list) {
WCHAR buf[39];
HKEY clsid_key;
StringFromGUID2(list->clsid, buf, 39);
res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
if (list->name) {
res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
(CONST BYTE*)(list->name),
strlen(list->name) + 1);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
if (list->ips) {
res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
if (list->ips32) {
HKEY ips32_key;
res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL,
&ips32_key, NULL);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
(CONST BYTE*)list->ips32,
lstrlenA(list->ips32) + 1);
if (res == ERROR_SUCCESS && list->ips32_tmodel)
res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
(CONST BYTE*)list->ips32_tmodel,
strlen(list->ips32_tmodel) + 1);
RegCloseKey(ips32_key);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
if (list->progid) {
res = register_key_defvalueA(clsid_key, progid_keyname,
list->progid);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
res = register_progid(buf, list->progid, NULL,
list->name, list->progid_extra);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
if (list->viprogid) {
res = register_key_defvalueA(clsid_key, viprogid_keyname,
list->viprogid);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
res = register_progid(buf, list->viprogid, list->progid,
list->name, list->progid_extra);
if (res != ERROR_SUCCESS) goto error_close_clsid_key;
}
error_close_clsid_key:
RegCloseKey(clsid_key);
}
error_close_coclass_key:
RegCloseKey(coclass_key);
error_return:
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
}
/***********************************************************************
* unregister_coclasses
*/
static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
{
LONG res = ERROR_SUCCESS;
HKEY coclass_key;
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
KEY_READ | KEY_WRITE, &coclass_key);
if (res == ERROR_FILE_NOT_FOUND) return S_OK;
if (res != ERROR_SUCCESS) goto error_return;
for (; res == ERROR_SUCCESS && list->clsid; ++list) {
WCHAR buf[39];
StringFromGUID2(list->clsid, buf, 39);
res = recursive_delete_keyW(coclass_key, buf);
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
if (list->progid) {
res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid);
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
}
if (list->viprogid) {
res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid);
if (res != ERROR_SUCCESS) goto error_close_coclass_key;
}
}
error_close_coclass_key:
RegCloseKey(coclass_key);
error_return:
return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
}
/***********************************************************************
* regsvr_key_guid
*/
static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
{
WCHAR buf[39];
StringFromGUID2(guid, buf, 39);
return register_key_defvalueW(base, name, buf);
}
/***********************************************************************
* regsvr_key_defvalueW
*/
static LONG register_key_defvalueW(
HKEY base,
WCHAR const *name,
WCHAR const *value)
{
LONG res;
HKEY key;
res = RegCreateKeyExW(base, name, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &key, NULL);
if (res != ERROR_SUCCESS) return res;
res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
(lstrlenW(value) + 1) * sizeof(WCHAR));
RegCloseKey(key);
return res;
}
/***********************************************************************
* regsvr_key_defvalueA
*/
static LONG register_key_defvalueA(
HKEY base,
WCHAR const *name,
char const *value)
{
LONG res;
HKEY key;
res = RegCreateKeyExW(base, name, 0, NULL, 0,
KEY_READ | KEY_WRITE, NULL, &key, NULL);
if (res != ERROR_SUCCESS) return res;
res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
lstrlenA(value) + 1);
RegCloseKey(key);
return res;
}
/***********************************************************************
* regsvr_progid
*/
static LONG register_progid(
WCHAR const *clsid,
char const *progid,
char const *curver_progid,
char const *name,
char const *extra)
{
LONG res;
HKEY progid_key;
res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
NULL, 0, KEY_READ | KEY_WRITE, NULL,
&progid_key, NULL);
if (res != ERROR_SUCCESS) return res;
if (name) {
res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
(CONST BYTE*)name, strlen(name) + 1);
if (res != ERROR_SUCCESS) goto error_close_progid_key;
}
if (clsid) {
res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
if (res != ERROR_SUCCESS) goto error_close_progid_key;
}
if (curver_progid) {
res = register_key_defvalueA(progid_key, curver_keyname,
curver_progid);
if (res != ERROR_SUCCESS) goto error_close_progid_key;
}
if (extra) {
HKEY extra_key;
res = RegCreateKeyExA(progid_key, extra, 0,
NULL, 0, KEY_READ | KEY_WRITE, NULL,
&extra_key, NULL);
if (res == ERROR_SUCCESS)
RegCloseKey(extra_key);
}
error_close_progid_key:
RegCloseKey(progid_key);
return res;
}
/***********************************************************************
* recursive_delete_key
*/
static LONG recursive_delete_key(HKEY key)
{
LONG res;
WCHAR subkey_name[MAX_PATH];
DWORD cName;
HKEY subkey;
for (;;) {
cName = sizeof(subkey_name) / sizeof(WCHAR);
res = RegEnumKeyExW(key, 0, subkey_name, &cName,
NULL, NULL, NULL, NULL);
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) {
res = ERROR_SUCCESS; /* presumably we're done enumerating */
break;
}
res = RegOpenKeyExW(key, subkey_name, 0,
KEY_READ | KEY_WRITE, &subkey);
if (res == ERROR_FILE_NOT_FOUND) continue;
if (res != ERROR_SUCCESS) break;
res = recursive_delete_key(subkey);
RegCloseKey(subkey);
if (res != ERROR_SUCCESS) break;
}
if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0);
return res;
}
/***********************************************************************
* recursive_delete_keyA
*/
static LONG recursive_delete_keyA(HKEY base, char const *name)
{
LONG res;
HKEY key;
res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key);
if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
if (res != ERROR_SUCCESS) return res;
res = recursive_delete_key(key);
RegCloseKey(key);
return res;
}
/***********************************************************************
* recursive_delete_keyW
*/
static LONG recursive_delete_keyW(HKEY base, WCHAR const *name)
{
LONG res;
HKEY key;
res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key);
if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS;
if (res != ERROR_SUCCESS) return res;
res = recursive_delete_key(key);
RegCloseKey(key);
return res;
}
/***********************************************************************
* coclass list
*/
static GUID const CLSID_DirectSoundBufferConfig = {
0xB2F586D4, 0x5558, 0x49D1, {0xA0,0x7B,0x32,0x49,0xDB,0xBB,0x33,0xC2} };
static struct regsvr_coclass const coclass_list[] = {
{ &CLSID_DirectSound,
"DirectSound Object",
NULL,
"dsound.dll",
"Both"
},
{ &CLSID_DirectSound8,
"DirectSound 8.0 Object",
NULL,
"dsound.dll",
"Both"
},
{ &CLSID_DirectSoundBufferConfig,
"DirectSoundBufferConfig Object",
NULL,
"dsound.dll",
"Both"
},
{ &CLSID_DirectSoundCapture,
"DirectSoundCapture Object",
NULL,
"dsound.dll",
"Both"
},
{ &CLSID_DirectSoundCapture8,
"DirectSoundCapture 8.0 Object",
NULL,
"dsound.dll",
"Both"
},
{ &CLSID_DirectSoundFullDuplex,
"DirectSoundFullDuplex Object",
NULL,
"dsound.dll",
"Both"
},
{ NULL } /* list terminator */
};
/***********************************************************************
* interface list
*/
static struct regsvr_interface const interface_list[] = {
{ NULL } /* list terminator */
};
/***********************************************************************
* DllRegisterServer (DSOUND.@)
*/
HRESULT WINAPI DSOUND_DllRegisterServer(void)
{
HRESULT hr;
TRACE("\n");
hr = register_coclasses(coclass_list);
if (SUCCEEDED(hr))
hr = register_interfaces(interface_list);
return hr;
}
/***********************************************************************
* DllUnregisterServer (DSOUND.@)
*/
HRESULT WINAPI DSOUND_DllUnregisterServer(void)
{
HRESULT hr;
TRACE("\n");
hr = unregister_coclasses(coclass_list);
if (SUCCEEDED(hr))
hr = unregister_interfaces(interface_list);
return hr;
}

1132
reactos/lib/dsound/sound3d.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,8 @@
Makefile
capture.ok
ds3d.ok
ds3d8.ok
dsound.ok
dsound8.ok
propset.ok
testlist.c

View file

@ -0,0 +1,19 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../../..
SRCDIR = @srcdir@
VPATH = @srcdir@
TESTDLL = dsound.dll
IMPORTS = dsound ole32 user32 kernel32
EXTRALIBS = -ldxguid -luuid -ldxerr8
CTESTS = \
capture.c \
ds3d.c \
ds3d8.c \
dsound.c \
dsound8.c \
propset.c
@MAKE_TEST_RULES@
### Dependencies:

View file

@ -0,0 +1,530 @@
/*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include <windows.h>
#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"
#include "dxerr8.h"
#include "dsound_test.h"
#define NOTIFICATIONS 5
static HRESULT (WINAPI *pDirectSoundCaptureCreate)(LPCGUID,LPDIRECTSOUNDCAPTURE*,LPUNKNOWN)=NULL;
static HRESULT (WINAPI *pDirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
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;
}
static char * format_string(WAVEFORMATEX* wfx)
{
static char str[64];
sprintf(str, "%5ldx%2dx%d %s",
wfx->nSamplesPerSec, wfx->wBitsPerSample, wfx->nChannels,
get_format_str(wfx->wFormatTag));
return str;
}
typedef struct {
char* wave;
DWORD wave_len;
LPDIRECTSOUNDCAPTUREBUFFER dscbo;
LPWAVEFORMATEX wfx;
DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS];
HANDLE event[NOTIFICATIONS];
LPDIRECTSOUNDNOTIFY notify;
DWORD buffer_size;
DWORD read;
DWORD offset;
DWORD size;
DWORD last_pos;
} capture_state_t;
static int 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: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
return 0;
rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,
&ptr1,&len1,&ptr2,&len2,0);
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Lock() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
return 0;
rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Unlock() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
return 0;
state->offset = (state->offset + state->size) % state->buffer_size;
return 1;
}
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: %s\n",
DXGetErrorString8(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: %s\n",
DXGetErrorString8(rc));
dscbcaps.dwSize=sizeof(dscbcaps);
rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetCaps() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && winetest_debug > 1) {
trace(" Caps: size = %ld flags=0x%08lx buffer size=%ld\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: %s\n",
DXGetErrorString8(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=%s, size=%ld\n",
DXGetErrorString8(rc),size);
rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetFormat() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && winetest_debug > 1) {
trace(" Format: tag=0x%04x %ldx%dx%d avg.B/s=%ld 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: %s\n",
DXGetErrorString8(rc));
rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && winetest_debug > 1) {
trace(" Status=0x%04lx\n",status);
}
ZeroMemory(&state, sizeof(state));
state.dscbo=dscbo;
state.wfx=&wfx;
state.buffer_size = dscbcaps.dwBufferBytes;
for (i = 0; i < NOTIFICATIONS; i++)
state.event[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
state.size = dscbcaps.dwBufferBytes / NOTIFICATIONS;
rc=IDirectSoundCaptureBuffer_QueryInterface(dscbo,&IID_IDirectSoundNotify,
(void **)&(state.notify));
ok((rc==DS_OK)&&(state.notify!=NULL),
"IDirectSoundCaptureBuffer_QueryInterface() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
return;
for (i = 0; i < NOTIFICATIONS; i++) {
state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
state.posnotify[i].hEventNotify = state.event[i];
}
rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,
state.posnotify);
ok(rc==DS_OK,"IDirectSoundNotify_SetNotificationPositions() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
return;
ref=IDirectSoundNotify_Release(state.notify);
ok(ref==0,"IDirectSoundNotify_Release(): has %d references, should have "
"0\n",ref);
if (ref!=0)
return;
if (record) {
rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Start() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
return;
rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_GetStatus() failed: %s\n",
DXGetErrorString8(rc));
ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
"GetStatus: bad status: %lx\n",status);
if (rc!=DS_OK)
return;
/* wait for the notifications */
for (i = 0; i < (NOTIFICATIONS * 2); i++) {
rc=MsgWaitForMultipleObjects(NOTIFICATIONS,state.event,FALSE,
3000,QS_ALLEVENTS);
ok(rc==(WAIT_OBJECT_0+(i%NOTIFICATIONS)),
"MsgWaitForMultipleObjects failed: 0x%lx\n",rc);
if (rc!=(WAIT_OBJECT_0+(i%NOTIFICATIONS))) {
ok((rc==WAIT_TIMEOUT)||(rc==WAIT_FAILED),
"Wrong notification: should be %d, got %ld\n",
i%NOTIFICATIONS,rc-WAIT_OBJECT_0);
}
if (!capture_buffer_service(&state))
break;
}
rc=IDirectSoundCaptureBuffer_Stop(dscbo);
ok(rc==DS_OK,"IDirectSoundCaptureBuffer_Stop() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
return;
}
}
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=pDirectSoundCaptureCreate(lpGuid,NULL,NULL);
ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate() should have "
"returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK) {
ref=IDirectSoundCapture_Release(dsco);
ok(ref==0,"IDirectSoundCapture_Release() has %d references, should "
"have 0\n",ref);
}
rc=pDirectSoundCaptureCreate(lpGuid,&dsco,NULL);
ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate() failed: "
"%s\n",DXGetErrorString8(rc));
if (rc!=DS_OK) {
if (rc==DSERR_NODRIVER)
trace(" No Driver\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: %s\n",DXGetErrorString8(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: %s\n",DXGetErrorString8(rc));
dsccaps.dwSize=sizeof(dsccaps);
rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
ok(rc==DS_OK,"IDirectSoundCapture_GetCaps() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && winetest_debug > 1) {
trace(" Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\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: %s\n",
DXGetErrorString8(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 %s\n",
DXGetErrorString8(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 :%s\n",
DXGetErrorString8(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: %s\n",
DXGetErrorString8(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<NB_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_ALLOCATED),
"IDirectSoundCapture_CreateCaptureBuffer() failed to create a "
"capture buffer: %s\n",DXGetErrorString8(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_ALLOCATED)
trace(" Already In Use\n");
}
/* 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;
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: %s\n",DXGetErrorString8(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,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 %s\n",DXGetErrorString8(rc));
#endif
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 capture_tests()
{
HRESULT rc;
rc=pDirectSoundCaptureEnumerateA(&dscenum_callback,NULL);
ok(rc==DS_OK,"DirectSoundCaptureEnumerateA() failed: %s\n",
DXGetErrorString8(rc));
}
START_TEST(capture)
{
HMODULE hDsound;
hDsound = LoadLibraryA("dsound.dll");
if (!hDsound) {
trace("dsound.dll not found\n");
return;
}
pDirectSoundCaptureCreate=(void*)GetProcAddress(hDsound,"DirectSoundCaptureCreate");
pDirectSoundCaptureEnumerateA=(void*)GetProcAddress(hDsound,"DirectSoundCaptureEnumerateA");
if (!pDirectSoundCaptureCreate || !pDirectSoundCaptureEnumerateA)
{
trace("capture test skipped\n");
return;
}
capture_tests();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,759 @@
/*
* Tests basic sound playback in DirectSound.
* In particular we test each standard Windows sound format to make sure
* we handle the sound card/driver quirks correctly.
*
* Part of this test involves playing test tones. But this only makes
* sense if someone is going to carefully listen to it, and would only
* bother everyone else.
* So this is only done if the test is being run in interactive mode.
*
* Copyright (c) 2002-2004 Francois Gouget
*
* 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
*/
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include <windows.h>
#include <math.h>
#include <stdlib.h>
#include "wine/test.h"
#include "windef.h"
#include "wingdi.h"
#include "dsound.h"
#include "dxerr8.h"
#include "dsconf.h"
#include "dsound_test.h"
static void IDirectSound_test(LPDIRECTSOUND dso, BOOL initialized,
LPCGUID lpGuid)
{
HRESULT rc;
DSCAPS dscaps;
int ref;
IUnknown * unknown;
IDirectSound * ds;
IDirectSound8 * ds8;
DWORD speaker_config, new_speaker_config;
/* Try to Query for objects */
rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK)
IDirectSound_Release(unknown);
rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK)
IDirectSound_Release(ds);
rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
"should have failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK)
IDirectSound8_Release(ds8);
if (initialized == FALSE) {
/* try unitialized object */
rc=IDirectSound_GetCaps(dso,0);
ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
"should have returned DSERR_UNINITIALIZED, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound_GetCaps(dso,&dscaps);
ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
"should have returned DSERR_UNINITIALIZED, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound_Compact(dso);
ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
"should have returned DSERR_UNINITIALIZED, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
"should have returned DSERR_UNINITIALIZED, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound_Initialize(dso,lpGuid);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc));
if (rc==DSERR_NODRIVER) {
trace(" No Driver\n");
return;
} else if (rc==DSERR_ALLOCATED) {
trace(" Already Allocated\n");
return;
}
}
/* DSOUND: Error: Invalid caps buffer */
rc=IDirectSound_GetCaps(dso,0);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
"should have returned DSERR_INVALIDPARAM, returned: %s\n",
DXGetErrorString8(rc));
ZeroMemory(&dscaps, sizeof(dscaps));
/* DSOUND: Error: Invalid caps buffer */
rc=IDirectSound_GetCaps(dso,&dscaps);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
"should have returned DSERR_INVALIDPARAM, returned: %s\n",
DXGetErrorString8(rc));
dscaps.dwSize=sizeof(dscaps);
/* DSOUND: Running on a certified driver */
rc=IDirectSound_GetCaps(dso,&dscaps);
ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
rc=IDirectSound_Compact(dso);
ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound_Compact(dso);
ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));
rc=IDirectSound_GetSpeakerConfig(dso,0);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
"should have returned DSERR_INVALIDPARAM, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
DXGetErrorString8(rc));
speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
DSSPEAKER_GEOMETRY_WIDE);
rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK) {
rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && speaker_config!=new_speaker_config)
trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
"config: expected 0x%08lx, got 0x%08lx\n",
speaker_config,new_speaker_config);
}
ref=IDirectSound_Release(dso);
ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
}
static void IDirectSound_tests()
{
HRESULT rc;
LPDIRECTSOUND dso=NULL;
trace("Testing IDirectSound\n");
/* try the COM class factory method of creation with no device specified */
rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound, (void**)&dso);
ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
DXGetErrorString8(rc));
if (dso)
IDirectSound_test(dso, FALSE, NULL);
/* try the COM class factory method of creation with default playback
* device specified */
rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound, (void**)&dso);
ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
DXGetErrorString8(rc));
if (dso)
IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
/* try the COM class factory method of creation with default voice
* playback device specified */
rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound, (void**)&dso);
ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
DXGetErrorString8(rc));
if (dso)
IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
/* try the COM class factory method of creation with a bad
* IID specified */
rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
&CLSID_DirectSoundPrivate, (void**)&dso);
ok(rc==E_NOINTERFACE,
"CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
"should have failed: %s\n",DXGetErrorString8(rc));
/* try the COM class factory method of creation with a bad
* GUID and IID specified */
rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound, (void**)&dso);
ok(rc==REGDB_E_CLASSNOTREG,
"CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
"should have failed: %s\n",DXGetErrorString8(rc));
/* try with no device specified */
rc=DirectSoundCreate(NULL,&dso,NULL);
ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
if (rc==S_OK && dso)
IDirectSound_test(dso, TRUE, NULL);
/* try with default playback device specified */
rc=DirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && dso)
IDirectSound_test(dso, TRUE, NULL);
/* try with default voice playback device specified */
rc=DirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && dso)
IDirectSound_test(dso, TRUE, NULL);
/* try with a bad device specified */
rc=DirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
"should have failed: %s\n",DXGetErrorString8(rc));
}
static HRESULT test_dsound(LPGUID lpGuid)
{
HRESULT rc;
LPDIRECTSOUND dso=NULL;
int ref;
/* DSOUND: Error: Invalid interface buffer */
rc=DirectSoundCreate(lpGuid,0,NULL);
ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
"DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
/* Create the DirectSound object */
rc=DirectSoundCreate(lpGuid,&dso,NULL);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
return rc;
/* Try the enumerated device */
IDirectSound_test(dso, TRUE, lpGuid);
/* Try the COM class factory method of creation with enumerated device */
rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound, (void**)&dso);
ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
DXGetErrorString8(rc));
if (dso)
IDirectSound_test(dso, FALSE, lpGuid);
/* Create a DirectSound object */
rc=DirectSoundCreate(lpGuid,&dso,NULL);
ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK) {
LPDIRECTSOUND dso1=NULL;
/* Create a second DirectSound object */
rc=DirectSoundCreate(lpGuid,&dso1,NULL);
ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK) {
/* Release the second DirectSound object */
ref=IDirectSound_Release(dso1);
ok(ref==0,"IDirectSound_Release() has %d references, should have "
"0\n",ref);
ok(dso!=dso1,"DirectSound objects should be unique: "
"dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
}
/* Release the first DirectSound object */
ref=IDirectSound_Release(dso);
ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
ref);
if (ref!=0)
return DSERR_GENERIC;
} else
return rc;
/* Create a DirectSound object */
rc=DirectSoundCreate(lpGuid,&dso,NULL);
ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK) {
LPDIRECTSOUNDBUFFER secondary;
DSBUFFERDESC bufdesc;
WAVEFORMATEX wfx;
init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
bufdesc.lpwfxFormat=&wfx;
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK && secondary!=NULL,
"IDirectSound_CreateSoundBuffer() failed to create a secondary "
"buffer %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && secondary!=NULL) {
LPDIRECTSOUND3DBUFFER buffer3d;
rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
(void **)&buffer3d);
ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
"failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && buffer3d!=NULL) {
ref=IDirectSound3DBuffer_AddRef(buffer3d);
ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
"should have 2\n",ref);
}
ref=IDirectSoundBuffer_AddRef(secondary);
ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
"should have 2\n",ref);
}
/* release with buffer */
ref=IDirectSound_Release(dso);
ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
ref);
if (ref!=0)
return DSERR_GENERIC;
} else
return rc;
return DS_OK;
}
static HRESULT test_primary(LPGUID lpGuid)
{
HRESULT rc;
LPDIRECTSOUND dso=NULL;
LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
DSBUFFERDESC bufdesc;
DSCAPS dscaps;
WAVEFORMATEX wfx;
int ref;
/* Create the DirectSound object */
rc=DirectSoundCreate(lpGuid,&dso,NULL);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
return rc;
/* Get the device capabilities */
ZeroMemory(&dscaps, sizeof(dscaps));
dscaps.dwSize=sizeof(dscaps);
rc=IDirectSound_GetCaps(dso,&dscaps);
ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
/* DSOUND: Error: Invalid buffer description pointer */
rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
ok(rc==DSERR_INVALIDPARAM,
"IDirectSound_CreateSoundBuffer() should have failed: %s\n",
DXGetErrorString8(rc));
/* DSOUND: Error: Invalid buffer description pointer */
rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
ok(rc==DSERR_INVALIDPARAM && primary==0,
"IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
"dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
/* DSOUND: Error: Invalid buffer description pointer */
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
ok(rc==DSERR_INVALIDPARAM && primary==0,
"IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
"dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
ZeroMemory(&bufdesc, sizeof(bufdesc));
/* DSOUND: Error: Invalid size */
/* DSOUND: Error: Invalid buffer description */
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DSERR_INVALIDPARAM && primary==0,
"IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
"primary=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
/* We must call SetCooperativeLevel before calling CreateSoundBuffer */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
/* Testing the primary buffer */
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
bufdesc.lpwfxFormat = &wfx;
init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
"returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
if (rc==DS_OK && primary!=NULL)
IDirectSoundBuffer_Release(primary);
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK && primary!=NULL,
"IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
"%s\n",DXGetErrorString8(rc));
if (rc==DS_OK && primary!=NULL) {
LONG vol;
/* Try to create a second primary buffer */
/* DSOUND: Error: The primary buffer already exists.
* Any changes made to the buffer description will be ignored. */
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
ok(rc==DS_OK && second==primary,
"IDirectSound_CreateSoundBuffer() should have returned original "
"primary buffer: %s\n",DXGetErrorString8(rc));
ref=IDirectSoundBuffer_Release(second);
ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
"should have 1\n",ref);
/* Try to duplicate a primary buffer */
/* DSOUND: Error: Can't duplicate primary buffers */
rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
/* rc=0x88780032 */
ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
"should have failed %s\n",DXGetErrorString8(rc));
rc=IDirectSoundBuffer_GetVolume(primary,&vol);
ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
DXGetErrorString8(rc));
if (winetest_interactive) {
trace("Playing a 5 seconds reference tone at the current "
"volume.\n");
if (rc==DS_OK)
trace("(the current volume is %ld according to DirectSound)\n",
vol);
trace("All subsequent tones should be identical to this one.\n");
trace("Listen for stutter, changes in pitch, volume, etc.\n");
}
test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
!(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
"should have 0\n",ref);
}
/* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
EXIT:
ref=IDirectSound_Release(dso);
ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
if (ref!=0)
return DSERR_GENERIC;
return rc;
}
/*
* Test the primary buffer at different formats while keeping the
* secondary buffer at a constant format.
*/
static HRESULT test_primary_secondary(LPGUID lpGuid)
{
HRESULT rc;
LPDIRECTSOUND dso=NULL;
LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
DSBUFFERDESC bufdesc;
DSCAPS dscaps;
WAVEFORMATEX wfx, wfx2;
int f,ref;
/* Create the DirectSound object */
rc=DirectSoundCreate(lpGuid,&dso,NULL);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
return rc;
/* Get the device capabilities */
ZeroMemory(&dscaps, sizeof(dscaps));
dscaps.dwSize=sizeof(dscaps);
rc=IDirectSound_GetCaps(dso,&dscaps);
ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
/* We must call SetCooperativeLevel before creating primary buffer */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK && primary!=NULL,
"IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
"%s\n",DXGetErrorString8(rc));
if (rc==DS_OK && primary!=NULL) {
for (f=0;f<NB_FORMATS;f++) {
/* We must call SetCooperativeLevel to be allowed to call
* SetFormat */
/* DSOUND: Setting DirectSound cooperative level to
* DSSCL_PRIORITY */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
formats[f][2]);
wfx2=wfx;
rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
DXGetErrorString8(rc));
/* There is no garantee that SetFormat will actually change the
* format to what we asked for. It depends on what the soundcard
* supports. So we must re-query the format.
*/
rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK &&
(wfx.wFormatTag!=wfx2.wFormatTag ||
wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
wfx.nChannels!=wfx2.nChannels)) {
trace("Requested primary format tag=0x%04x %ldx%dx%d "
"avg.B/s=%ld align=%d\n",
wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
}
/* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
secondary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
bufdesc.lpwfxFormat=&wfx2;
if (winetest_interactive) {
trace(" Testing a primary buffer at %ldx%dx%d with a "
"secondary buffer at %ldx%dx%d\n",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
}
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK && secondary!=NULL,
"IDirectSound_CreateSoundBuffer() failed to create a secondary "
"buffer %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && secondary!=NULL) {
test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
winetest_interactive,1.0,0,NULL,0,0);
ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
"should have 0\n",ref);
}
}
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
"should have 0\n",ref);
}
/* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
EXIT:
ref=IDirectSound_Release(dso);
ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
if (ref!=0)
return DSERR_GENERIC;
return rc;
}
static HRESULT test_secondary(LPGUID lpGuid)
{
HRESULT rc;
LPDIRECTSOUND dso=NULL;
LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
DSBUFFERDESC bufdesc;
DSCAPS dscaps;
WAVEFORMATEX wfx;
DWORD f;
int ref;
/* Create the DirectSound object */
rc=DirectSoundCreate(lpGuid,&dso,NULL);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
return rc;
/* Get the device capabilities */
ZeroMemory(&dscaps, sizeof(dscaps));
dscaps.dwSize=sizeof(dscaps);
rc=IDirectSound_GetCaps(dso,&dscaps);
ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
/* We must call SetCooperativeLevel before creating primary buffer */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK && primary!=NULL,
"IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
"%s\n",DXGetErrorString8(rc));
if (rc==DS_OK && primary!=NULL) {
for (f=0;f<NB_FORMATS;f++) {
init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
formats[f][2]);
secondary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
"should have returned DSERR_INVALIDPARAM, returned: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && secondary!=NULL)
IDirectSoundBuffer_Release(secondary);
secondary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
bufdesc.lpwfxFormat=&wfx;
if (winetest_interactive) {
trace(" Testing a secondary buffer at %ldx%dx%d\n",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
}
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK && secondary!=NULL,
"IDirectSound_CreateSoundBuffer() failed to create a secondary "
"buffer %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && secondary!=NULL) {
test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
winetest_interactive,1.0,0,NULL,0,0);
ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
"should have 0\n",ref);
}
}
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
"should have 0\n",ref);
}
/* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
EXIT:
ref=IDirectSound_Release(dso);
ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
if (ref!=0)
return DSERR_GENERIC;
return rc;
}
static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
LPCSTR lpcstrModule, LPVOID lpContext)
{
HRESULT rc;
trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
rc = test_dsound(lpGuid);
if (rc == DSERR_NODRIVER)
trace(" No Driver\n");
else if (rc == DSERR_ALLOCATED)
trace(" Already In Use\n");
else {
test_primary(lpGuid);
test_primary_secondary(lpGuid);
test_secondary(lpGuid);
}
return 1;
}
static void dsound_tests()
{
HRESULT rc;
rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
}
START_TEST(dsound)
{
CoInitialize(NULL);
IDirectSound_tests();
dsound_tests();
}

View file

@ -0,0 +1,794 @@
/*
* Tests basic sound playback in DirectSound.
* In particular we test each standard Windows sound format to make sure
* we handle the sound card/driver quirks correctly.
*
* Part of this test involves playing test tones. But this only makes
* sense if someone is going to carefully listen to it, and would only
* bother everyone else.
* So this is only done if the test is being run in interactive mode.
*
* Copyright (c) 2002-2004 Francois Gouget
*
* 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
*/
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include <windows.h>
#include <math.h>
#include <stdlib.h>
#include "wine/test.h"
#include "windef.h"
#include "wingdi.h"
#include "dsound.h"
#include "dxerr8.h"
#include "dsconf.h"
#include "dsound_test.h"
static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;
static void IDirectSound8_test(LPDIRECTSOUND8 dso, BOOL initialized,
LPCGUID lpGuid)
{
HRESULT rc;
DSCAPS dscaps;
int ref;
IUnknown * unknown;
IDirectSound * ds;
IDirectSound8 * ds8;
DWORD speaker_config, new_speaker_config;
DWORD certified;
/* Try to Query for objects */
rc=IDirectSound8_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IUnknown) failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK)
IDirectSound8_Release(unknown);
rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound) failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK)
IDirectSound_Release(ds);
rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound8) "
"should have returned DSERR_INVALIDPARAM, returned: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK)
IDirectSound8_Release(ds8);
if (initialized == FALSE) {
/* try unitialized object */
rc=IDirectSound8_GetCaps(dso,0);
ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps(NULL) "
"should have returned DSERR_UNINITIALIZED, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound8_GetCaps(dso,&dscaps);
ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps() "
"should have returned DSERR_UNINITIALIZED, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound8_Compact(dso);
ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_Compact() "
"should have returned DSERR_UNINITIALIZED, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetSpeakerConfig() "
"should have returned DSERR_UNINITIALIZED, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound8_VerifyCertification(dso, &certified);
ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_VerifyCertification() "
"should have returned DSERR_UNINITIALIZED, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound8_Initialize(dso,lpGuid);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"IDirectSound8_Initialize() failed: %s\n",DXGetErrorString8(rc));
if (rc==DSERR_NODRIVER) {
trace(" No Driver\n");
return;
} else if (rc==DSERR_ALLOCATED) {
trace(" Already In Use\n");
return;
}
}
/* DSOUND: Error: Invalid caps buffer */
rc=IDirectSound8_GetCaps(dso,0);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
"should have returned DSERR_INVALIDPARAM, returned: %s\n",
DXGetErrorString8(rc));
ZeroMemory(&dscaps, sizeof(dscaps));
/* DSOUND: Error: Invalid caps buffer */
rc=IDirectSound8_GetCaps(dso,&dscaps);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
"should have returned DSERR_INVALIDPARAM, returned: %s\n",
DXGetErrorString8(rc));
dscaps.dwSize=sizeof(dscaps);
/* DSOUND: Running on a certified driver */
rc=IDirectSound8_GetCaps(dso,&dscaps);
ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
rc=IDirectSound8_Compact(dso);
ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound8_Compact() failed: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound8_Compact(dso);
ok(rc==DS_OK,"IDirectSound8_Compact() failed: %s\n",DXGetErrorString8(rc));
rc=IDirectSound8_GetSpeakerConfig(dso,0);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetSpeakerConfig(NULL) "
"should have returned DSERR_INVALIDPARAM, returned: %s\n",
DXGetErrorString8(rc));
rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %s\n",
DXGetErrorString8(rc));
speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
DSSPEAKER_GEOMETRY_WIDE);
rc=IDirectSound8_SetSpeakerConfig(dso,speaker_config);
ok(rc==DS_OK,"IDirectSound8_SetSpeakerConfig() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK) {
rc=IDirectSound8_GetSpeakerConfig(dso,&new_speaker_config);
ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && speaker_config!=new_speaker_config)
trace("IDirectSound8_GetSpeakerConfig() failed to set speaker "
"config: expected 0x%08lx, got 0x%08lx\n",
speaker_config,new_speaker_config);
}
rc=IDirectSound8_VerifyCertification(dso, &certified);
ok(rc==DS_OK||rc==E_NOTIMPL,"IDirectSound8_VerifyCertification() failed: %s\n",
DXGetErrorString8(rc));
ref=IDirectSound8_Release(dso);
ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
}
static void IDirectSound8_tests()
{
HRESULT rc;
LPDIRECTSOUND8 dso=NULL;
trace("Testing IDirectSound8\n");
/* try the COM class factory method of creation with no device specified */
rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound8, (void**)&dso);
ok(rc==S_OK,"CoCreateInstance() failed: %s\n",DXGetErrorString8(rc));
if (dso)
IDirectSound8_test(dso, FALSE, NULL);
/* try the COM class factory method of creation with default playback
* device specified */
rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound8, (void**)&dso);
ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %s\n",
DXGetErrorString8(rc));
if (dso)
IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultPlayback);
/* try the COM class factory method of creation with default voice
* playback device specified */
rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound8, (void**)&dso);
ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %s\n",
DXGetErrorString8(rc));
if (dso)
IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
/* try the COM class factory method of creation with a bad
* IID specified */
rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
&CLSID_DirectSoundPrivate, (void**)&dso);
ok(rc==E_NOINTERFACE,
"CoCreateInstance(CLSID_DirectSound8,CLSID_DirectSoundPrivate) "
"should have failed: %s\n",DXGetErrorString8(rc));
/* try the COM class factory method of creation with a bad
* GUID and IID specified */
rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound8, (void**)&dso);
ok(rc==REGDB_E_CLASSNOTREG,
"CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound8) "
"should have failed: %s\n",DXGetErrorString8(rc));
/* try with no device specified */
rc=pDirectSoundCreate8(NULL,&dso,NULL);
ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && dso)
IDirectSound8_test(dso, TRUE, NULL);
/* try with default playback device specified */
rc=pDirectSoundCreate8(&DSDEVID_DefaultPlayback,&dso,NULL);
ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && dso)
IDirectSound8_test(dso, TRUE, NULL);
/* try with default voice playback device specified */
rc=pDirectSoundCreate8(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && dso)
IDirectSound8_test(dso, TRUE, NULL);
/* try with a bad device specified */
rc=pDirectSoundCreate8(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
ok(rc==DSERR_NODRIVER,"DirectSoundCreate8(DSDEVID_DefaultVoiceCapture) "
"should have failed: %s\n",DXGetErrorString8(rc));
}
static HRESULT test_dsound8(LPGUID lpGuid)
{
HRESULT rc;
LPDIRECTSOUND8 dso=NULL;
int ref;
/* DSOUND: Error: Invalid interface buffer */
rc=pDirectSoundCreate8(lpGuid,0,NULL);
ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate8() should have returned "
"DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
/* Create the DirectSound8 object */
rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
return rc;
/* Try the enumerated device */
IDirectSound8_test(dso, TRUE, lpGuid);
/* Try the COM class factory method of creation with enumerated device */
rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound8, (void**)&dso);
ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
DXGetErrorString8(rc));
if (dso)
IDirectSound8_test(dso, FALSE, lpGuid);
/* Create a DirectSound8 object */
rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
ok(rc==DS_OK,"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK) {
LPDIRECTSOUND8 dso1=NULL;
/* Create a second DirectSound8 object */
rc=pDirectSoundCreate8(lpGuid,&dso1,NULL);
ok(rc==DS_OK,"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK) {
/* Release the second DirectSound8 object */
ref=IDirectSound8_Release(dso1);
ok(ref==0,"IDirectSound8_Release() has %d references, "
"should have 0\n",ref);
ok(dso!=dso1,"DirectSound8 objects should be unique: "
"dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
}
/* Release the first DirectSound8 object */
ref=IDirectSound8_Release(dso);
ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
ref);
if (ref!=0)
return DSERR_GENERIC;
} else
return rc;
/* Create a DirectSound8 object */
rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
ok(rc==DS_OK,"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK) {
LPDIRECTSOUNDBUFFER secondary;
DSBUFFERDESC bufdesc;
WAVEFORMATEX wfx;
init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
bufdesc.lpwfxFormat=&wfx;
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK && secondary!=NULL,
"IDirectSound8_CreateSoundBuffer() failed to create a secondary "
"buffer: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && secondary!=NULL) {
LPDIRECTSOUND3DBUFFER buffer3d;
LPDIRECTSOUNDBUFFER8 buffer8;
rc=IDirectSound8_QueryInterface(secondary,
&IID_IDirectSound3DBuffer,
(void **)&buffer3d);
ok(rc==DS_OK && buffer3d!=NULL,
"IDirectSound8_QueryInterface() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && buffer3d!=NULL) {
ref=IDirectSound3DBuffer_AddRef(buffer3d);
ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
"should have 2\n",ref);
}
rc=IDirectSound8_QueryInterface(secondary,
&IID_IDirectSoundBuffer8,
(void **)&buffer8);
if (rc==DS_OK && buffer8!=NULL) {
ref=IDirectSoundBuffer8_AddRef(buffer8);
ok(ref==3,"IDirectSoundBuffer8_AddRef() has %d references, "
"should have 3\n",ref);
}
ref=IDirectSoundBuffer_AddRef(secondary);
ok(ref==4,"IDirectSoundBuffer_AddRef() has %d references, "
"should have 4\n",ref);
}
/* release with buffer */
ref=IDirectSound8_Release(dso);
ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
ref);
if (ref!=0)
return DSERR_GENERIC;
} else
return rc;
return DS_OK;
}
static HRESULT test_primary8(LPGUID lpGuid)
{
HRESULT rc;
LPDIRECTSOUND8 dso=NULL;
LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
DSBUFFERDESC bufdesc;
DSCAPS dscaps;
WAVEFORMATEX wfx;
int ref;
/* Create the DirectSound object */
rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
return rc;
/* Get the device capabilities */
ZeroMemory(&dscaps, sizeof(dscaps));
dscaps.dwSize=sizeof(dscaps);
rc=IDirectSound8_GetCaps(dso,&dscaps);
ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
/* DSOUND: Error: Invalid buffer description pointer */
rc=IDirectSound8_CreateSoundBuffer(dso,0,0,NULL);
ok(rc==DSERR_INVALIDPARAM,
"IDirectSound8_CreateSoundBuffer should have returned "
"DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
/* DSOUND: Error: Invalid buffer description pointer */
rc=IDirectSound8_CreateSoundBuffer(dso,0,&primary,NULL);
ok(rc==DSERR_INVALIDPARAM && primary==0,
"IDirectSound8_CreateSoundBuffer() should have returned "
"DSERR_INVALIDPARAM, returned: rc=%s,dsbo=0x%lx\n",
DXGetErrorString8(rc),(DWORD)primary);
/* DSOUND: Error: Invalid buffer description pointer */
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,0,NULL);
ok(rc==DSERR_INVALIDPARAM && primary==0,
"IDirectSound8_CreateSoundBuffer() should have failed: rc=%s,"
"dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
ZeroMemory(&bufdesc, sizeof(bufdesc));
/* DSOUND: Error: Invalid size */
/* DSOUND: Error: Invalid buffer description */
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DSERR_INVALIDPARAM && primary==0,
"IDirectSound8_CreateSoundBuffer() should have failed: rc=%s,"
"primary=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
/* We must call SetCooperativeLevel before calling CreateSoundBuffer */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
/* Testing the primary buffer */
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
bufdesc.lpwfxFormat = &wfx;
init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() should have "
"returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
if (rc==DS_OK && primary!=NULL)
IDirectSoundBuffer_Release(primary);
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK && primary!=NULL,
"IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: "
"%s\n",DXGetErrorString8(rc));
if (rc==DS_OK && primary!=NULL) {
LONG vol;
/* Try to create a second primary buffer */
/* DSOUND: Error: The primary buffer already exists.
* Any changes made to the buffer description will be ignored. */
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
ok(rc==DS_OK && second==primary,
"IDirectSound8_CreateSoundBuffer() should have returned original "
"primary buffer: %s\n",DXGetErrorString8(rc));
ref=IDirectSoundBuffer_Release(second);
ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
"should have 1\n",ref);
/* Try to duplicate a primary buffer */
/* DSOUND: Error: Can't duplicate primary buffers */
rc=IDirectSound8_DuplicateSoundBuffer(dso,primary,&third);
/* rc=0x88780032 */
ok(rc!=DS_OK,"IDirectSound8_DuplicateSoundBuffer() primary buffer "
"should have failed %s\n",DXGetErrorString8(rc));
rc=IDirectSoundBuffer_GetVolume(primary,&vol);
ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
DXGetErrorString8(rc));
if (winetest_interactive) {
trace("Playing a 5 seconds reference tone at the current volume.\n");
if (rc==DS_OK)
trace("(the current volume is %ld according to DirectSound)\n",
vol);
trace("All subsequent tones should be identical to this one.\n");
trace("Listen for stutter, changes in pitch, volume, etc.\n");
}
test_buffer8(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
!(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
"should have 0\n",ref);
}
/* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
EXIT:
ref=IDirectSound8_Release(dso);
ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
if (ref!=0)
return DSERR_GENERIC;
return rc;
}
/*
* Test the primary buffer at different formats while keeping the
* secondary buffer at a constant format.
*/
static HRESULT test_primary_secondary8(LPGUID lpGuid)
{
HRESULT rc;
LPDIRECTSOUND8 dso=NULL;
LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
DSBUFFERDESC bufdesc;
DSCAPS dscaps;
WAVEFORMATEX wfx, wfx2;
int f,ref;
/* Create the DirectSound object */
rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
return rc;
/* Get the device capabilities */
ZeroMemory(&dscaps, sizeof(dscaps));
dscaps.dwSize=sizeof(dscaps);
rc=IDirectSound8_GetCaps(dso,&dscaps);
ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
/* We must call SetCooperativeLevel before creating primary buffer */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK && primary!=NULL,
"IDirectSound8_CreateSoundBuffer() failed to create a primary buffer "
"%s\n",DXGetErrorString8(rc));
if (rc==DS_OK && primary!=NULL) {
for (f=0;f<NB_FORMATS;f++) {
/* We must call SetCooperativeLevel to be allowed to call
* SetFormat */
/* DSOUND: Setting DirectSound cooperative level to
* DSSCL_PRIORITY */
rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
formats[f][2]);
wfx2=wfx;
rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
DXGetErrorString8(rc));
/* There is no garantee that SetFormat will actually change the
* format to what we asked for. It depends on what the soundcard
* supports. So we must re-query the format.
*/
rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK &&
(wfx.wFormatTag!=wfx2.wFormatTag ||
wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
wfx.nChannels!=wfx2.nChannels)) {
trace("Requested primary format tag=0x%04x %ldx%dx%d "
"avg.B/s=%ld align=%d\n",
wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
}
/* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
secondary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
bufdesc.lpwfxFormat=&wfx2;
if (winetest_interactive) {
trace(" Testing a primary buffer at %ldx%dx%d with a "
"secondary buffer at %ldx%dx%d\n",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
}
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK && secondary!=NULL,
"IDirectSound_CreateSoundBuffer() failed to create a secondary "
"buffer %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && secondary!=NULL) {
test_buffer8(dso,secondary,0,FALSE,0,FALSE,0,
winetest_interactive,1.0,0,NULL,0,0);
ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
"should have 0\n",ref);
}
}
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
"should have 0\n",ref);
}
/* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
EXIT:
ref=IDirectSound8_Release(dso);
ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
if (ref!=0)
return DSERR_GENERIC;
return rc;
}
static HRESULT test_secondary8(LPGUID lpGuid)
{
HRESULT rc;
LPDIRECTSOUND8 dso=NULL;
LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
DSBUFFERDESC bufdesc;
DSCAPS dscaps;
WAVEFORMATEX wfx;
DWORD f;
int ref;
/* Create the DirectSound object */
rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate8() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
return rc;
/* Get the device capabilities */
ZeroMemory(&dscaps, sizeof(dscaps));
dscaps.dwSize=sizeof(dscaps);
rc=IDirectSound8_GetCaps(dso,&dscaps);
ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
/* We must call SetCooperativeLevel before creating primary buffer */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK && primary!=NULL,
"IDirectSound8_CreateSoundBuffer() failed to create a primary buffer "
"%s\n",DXGetErrorString8(rc));
if (rc==DS_OK && primary!=NULL) {
for (f=0;f<NB_FORMATS;f++) {
init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
formats[f][2]);
secondary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() "
"should have returned DSERR_INVALIDPARAM, returned: %s\n",
DXGetErrorString8(rc));
if (rc==DS_OK && secondary!=NULL)
IDirectSoundBuffer_Release(secondary);
secondary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
bufdesc.lpwfxFormat=&wfx;
if (winetest_interactive) {
trace(" Testing a secondary buffer at %ldx%dx%d\n",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
}
rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK && secondary!=NULL,
"IDirectSound8_CreateSoundBuffer() failed to create a secondary "
"buffer: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK && secondary!=NULL) {
test_buffer8(dso,secondary,0,FALSE,0,FALSE,0,
winetest_interactive,1.0,0,NULL,0,0);
ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
"should have 0\n",ref);
}
}
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
"should have 0\n",ref);
}
/* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
EXIT:
ref=IDirectSound8_Release(dso);
ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
if (ref!=0)
return DSERR_GENERIC;
return rc;
}
static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
LPCSTR lpcstrModule, LPVOID lpContext)
{
HRESULT rc;
trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
rc = test_dsound8(lpGuid);
if (rc == DSERR_NODRIVER)
trace(" No Driver\n");
else if (rc == DSERR_ALLOCATED)
trace(" Already In Use\n");
else {
test_primary8(lpGuid);
test_primary_secondary8(lpGuid);
test_secondary8(lpGuid);
}
return 1;
}
static void dsound8_tests()
{
HRESULT rc;
rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
}
START_TEST(dsound8)
{
HMODULE hDsound;
CoInitialize(NULL);
hDsound = LoadLibraryA("dsound.dll");
if (!hDsound) {
trace("dsound.dll not found\n");
return;
}
pDirectSoundCreate8 = (void*)GetProcAddress(hDsound, "DirectSoundCreate8");
if (!pDirectSoundCreate8) {
trace("dsound8 test skipped\n");
return;
}
IDirectSound8_tests();
dsound8_tests();
}

View file

@ -0,0 +1,63 @@
/*
* Unit tests for dsound functions
*
* Copyright (c) 2004 Francois Gouget
*
* 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
*/
static const unsigned int formats[][4]={
{ 8000, 8, 1, 0 },
{ 8000, 8, 2, 0 },
{ 8000, 16, 1, 0 },
{ 8000, 16, 2, 0 },
{11025, 8, 1, WAVE_FORMAT_1M08 },
{11025, 8, 2, WAVE_FORMAT_1S08 },
{11025, 16, 1, WAVE_FORMAT_1M16 },
{11025, 16, 2, WAVE_FORMAT_1S16 },
{22050, 8, 1, WAVE_FORMAT_2M08 },
{22050, 8, 2, WAVE_FORMAT_2S08 },
{22050, 16, 1, WAVE_FORMAT_2M16 },
{22050, 16, 2, WAVE_FORMAT_2S16 },
{44100, 8, 1, WAVE_FORMAT_4M08 },
{44100, 8, 2, WAVE_FORMAT_4S08 },
{44100, 16, 1, WAVE_FORMAT_4M16 },
{44100, 16, 2, WAVE_FORMAT_4S16 },
{48000, 8, 1, WAVE_FORMAT_48M08 },
{48000, 8, 2, WAVE_FORMAT_48S08 },
{48000, 16, 1, WAVE_FORMAT_48M16 },
{48000, 16, 2, WAVE_FORMAT_48S16 },
{96000, 8, 1, WAVE_FORMAT_96M08 },
{96000, 8, 2, WAVE_FORMAT_96S08 },
{96000, 16, 1, WAVE_FORMAT_96M16 },
{96000, 16, 2, WAVE_FORMAT_96S16 }
};
#define NB_FORMATS (sizeof(formats)/sizeof(*formats))
/* The time slice determines how often we will service the buffer */
#define TIME_SLICE 31
#define BUFFER_LEN 400
extern char* wave_generate_la(WAVEFORMATEX*,double,DWORD*);
extern HWND get_hwnd(void);
extern void init_format(WAVEFORMATEX*,int,int,int,int);
extern void test_buffer(LPDIRECTSOUND,LPDIRECTSOUNDBUFFER,
BOOL,BOOL,LONG,BOOL,LONG,BOOL,double,BOOL,
LPDIRECTSOUND3DLISTENER,BOOL,BOOL);
extern void test_buffer8(LPDIRECTSOUND8,LPDIRECTSOUNDBUFFER,
BOOL,BOOL,LONG,BOOL,LONG,BOOL,double,BOOL,
LPDIRECTSOUND3DLISTENER,BOOL,BOOL);
extern const char * getDSBCAPS(DWORD xmask);

View file

@ -0,0 +1,413 @@
/*
* Unit tests for CLSID_DirectSoundPrivate property set functions
* (used by dxdiag)
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include <windows.h>
#include <math.h>
#include <stdlib.h>
#include "wine/test.h"
#include "windef.h"
#include "wingdi.h"
#include "dsound.h"
#include "initguid.h"
#include "dsconf.h"
#include "dxerr8.h"
#include "dsound_test.h"
#ifndef DSBCAPS_CTRLDEFAULT
#define DSBCAPS_CTRLDEFAULT \
DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME
#endif
DEFINE_GUID(DSPROPSETID_VoiceManager, \
0x62A69BAE,0xDF9D,0x11D1,0x99,0xA6,0x00,0xC0,0x4F,0xC9,0x9D,0x46);
DEFINE_GUID(DSPROPSETID_EAX20_ListenerProperties, \
0x306a6a8,0xb224,0x11d2,0x99,0xe5,0x0,0x0,0xe8,0xd8,0xc7,0x22);
DEFINE_GUID(DSPROPSETID_EAX20_BufferProperties, \
0x306a6a7,0xb224,0x11d2,0x99,0xe5,0x0,0x0,0xe8,0xd8,0xc7,0x22);
DEFINE_GUID(DSPROPSETID_I3DL2_ListenerProperties, \
0xDA0F0520,0x300A,0x11D3,0x8A,0x2B,0x00,0x60,0x97,0x0D,0xB0,0x11);
DEFINE_GUID(DSPROPSETID_I3DL2_BufferProperties, \
0xDA0F0521,0x300A,0x11D3,0x8A,0x2B,0x00,0x60,0x97,0x0D,0xB0,0x11);
DEFINE_GUID(DSPROPSETID_ZOOMFX_BufferProperties, \
0xCD5368E0,0x3450,0x11D3,0x8B,0x6E,0x00,0x10,0x5A,0x9B,0x7B,0xBC);
typedef HRESULT (CALLBACK * MYPROC)(REFCLSID, REFIID, LPVOID *);
BOOL CALLBACK callback(PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA data,
LPVOID context)
{
trace("found device:\n");
trace("\tType: %s\n",
data->Type == DIRECTSOUNDDEVICE_TYPE_EMULATED ? "Emulated" :
data->Type == DIRECTSOUNDDEVICE_TYPE_VXD ? "VxD" :
data->Type == DIRECTSOUNDDEVICE_TYPE_WDM ? "WDM" : "Unknown");
trace("\tDataFlow: %s\n",
data->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER ? "Render" :
data->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE ?
"Capture" : "Unknown");
trace("\tDeviceId: {%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
data->DeviceId.Data1,data->DeviceId.Data2,data->DeviceId.Data3,
data->DeviceId.Data4[0],data->DeviceId.Data4[1],
data->DeviceId.Data4[2],data->DeviceId.Data4[3],
data->DeviceId.Data4[4],data->DeviceId.Data4[5],
data->DeviceId.Data4[6],data->DeviceId.Data4[7]);
trace("\tDescription: %s\n", data->Description);
trace("\tModule: %s\n", data->Module);
trace("\tInterface: %s\n", data->Interface);
trace("\tWaveDeviceId: %ld\n", data->WaveDeviceId);
return TRUE;
}
static void propset_private_tests()
{
HMODULE hDsound;
HRESULT rc;
IClassFactory * pcf;
IKsPropertySet * pps;
MYPROC fProc;
ULONG support;
hDsound = LoadLibrary("dsound.dll");
ok(hDsound!=0,"LoadLibrary(dsound.dll) failed\n");
if (hDsound==0)
return;
fProc = (MYPROC)GetProcAddress(hDsound, "DllGetClassObject");
/* try direct sound first */
rc = (fProc)(&CLSID_DirectSound, &IID_IClassFactory, (void **)0);
ok(rc==DSERR_INVALIDPARAM,"DllGetClassObject(CLSID_DirectSound, "
"IID_IClassFactory) should have returned DSERR_INVALIDPARAM, "
"returned: %s\n",DXGetErrorString8(rc));
rc = (fProc)(&CLSID_DirectSound, &IID_IClassFactory, (void **)(&pcf));
ok(pcf!=0, "DllGetClassObject(CLSID_DirectSound, IID_IClassFactory) "
"failed: %s\n",DXGetErrorString8(rc));
if (pcf==0)
goto error;
/* direct sound doesn't have an IKsPropertySet */
rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
(void **)0);
ok(rc==DSERR_INVALIDPARAM, "CreateInstance(IID_IKsPropertySet) should have "
"returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
(void **)(&pps));
ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
"returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc));
/* and the direct sound 8 version */
rc = (fProc)(&CLSID_DirectSound8, &IID_IClassFactory, (void **)(&pcf));
ok(pcf!=0, "DllGetClassObject(CLSID_DirectSound8, IID_IClassFactory) "
"failed: %s\n",DXGetErrorString8(rc));
if (pcf==0)
goto error;
/* direct sound 8 doesn't have an IKsPropertySet */
rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
(void **)(&pps));
ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
"returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc));
/* try direct sound capture next */
rc = (fProc)(&CLSID_DirectSoundCapture, &IID_IClassFactory,
(void **)(&pcf));
ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundCapture, IID_IClassFactory) "
"failed: %s\n",DXGetErrorString8(rc));
if (pcf==0)
goto error;
/* direct sound capture doesn't have an IKsPropertySet */
rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
(void **)(&pps));
ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
"returned E_NOINTERFACE,returned: %s\n",DXGetErrorString8(rc));
/* and the direct sound capture 8 version */
rc = (fProc)(&CLSID_DirectSoundCapture8, &IID_IClassFactory,
(void **)(&pcf));
ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundCapture8, "
"IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc));
if (pcf==0)
goto error;
/* direct sound capture 8 doesn't have an IKsPropertySet */
rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
(void **)(&pps));
ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
"returned E_NOINTERFACE, returned: %s\n",DXGetErrorString8(rc));
/* try direct sound full duplex next */
rc = (fProc)(&CLSID_DirectSoundFullDuplex, &IID_IClassFactory,
(void **)(&pcf));
ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundFullDuplex, "
"IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc));
if (pcf==0)
goto error;
/* direct sound full duplex doesn't have an IKsPropertySet */
rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
(void **)(&pps));
ok(rc==E_NOINTERFACE, "CreateInstance(IID_IKsPropertySet) should have "
"returned NOINTERFACE, returned: %s\n",DXGetErrorString8(rc));
/* try direct sound private last */
rc = (fProc)(&CLSID_DirectSoundPrivate, &IID_IClassFactory,
(void **)(&pcf));
ok(pcf!=0, "DllGetClassObject(CLSID_DirectSoundPrivate, "
"IID_IClassFactory) failed: %s\n",DXGetErrorString8(rc));
if (pcf==0)
goto error;
/* direct sound private does have an IKsPropertySet */
rc = pcf->lpVtbl->CreateInstance(pcf, NULL, &IID_IKsPropertySet,
(void **)(&pps));
ok(rc==DS_OK, "CreateInstance(IID_IKsPropertySet) failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto error;
rc = pps->lpVtbl->QuerySupport(pps, &DSPROPSETID_DirectSoundDevice,
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION,
&support);
ok(rc==DS_OK, "QuerySupport(DSPROPSETID_DirectSoundDevice, "
"DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION) failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto error;
ok(support & KSPROPERTY_SUPPORT_GET,
"Couldn't get DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION: "
"support = 0x%lx\n",support);
ok(!(support & KSPROPERTY_SUPPORT_SET),
"Shouldn't be able to set DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION: "
"support = 0x%lx\n",support);
rc = pps->lpVtbl->QuerySupport(pps, &DSPROPSETID_DirectSoundDevice,
DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING, &support);
ok(rc==DS_OK, "QuerySupport(DSPROPSETID_DirectSoundDevice, "
"DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING) failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto error;
ok(support & KSPROPERTY_SUPPORT_GET,
"Couldn't get DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING: "
"support = 0x%lx\n",support);
ok(!(support & KSPROPERTY_SUPPORT_SET), "Shouldn't be able to set "
"DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING: support = "
"0x%lx\n",support);
rc = pps->lpVtbl->QuerySupport(pps, &DSPROPSETID_DirectSoundDevice,
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE,
&support);
ok(rc==DS_OK, "QuerySupport(DSPROPSETID_DirectSoundDevice, "
"DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE) failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto error;
ok(support & KSPROPERTY_SUPPORT_GET,
"Couldn't get DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE: "
"support = 0x%lx\n",support);
ok(!(support & KSPROPERTY_SUPPORT_SET),"Shouldn't be able to set "
"DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE: support = 0x%lx\n",support);
if (support & KSPROPERTY_SUPPORT_GET) {
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_DATA data;
ULONG bytes;
data.Callback = callback;
data.Context = 0;
rc = pps->lpVtbl->Get(pps, &DSPROPSETID_DirectSoundDevice,
DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE,
NULL, 0, &data, sizeof(data), &bytes);
ok(rc==DS_OK, "Couldn't enumerate: 0x%lx\n",rc);
}
error:
FreeLibrary(hDsound);
}
static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
LPCSTR lpcstrModule, LPVOID lpContext)
{
HRESULT rc;
LPDIRECTSOUND dso=NULL;
LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
DSBUFFERDESC bufdesc;
WAVEFORMATEX wfx;
int ref;
trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
rc=DirectSoundCreate(lpGuid,&dso,NULL);
ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
if (rc!=DS_OK) {
if (rc==DSERR_NODRIVER)
trace(" No Driver\n");
else if (rc == DSERR_ALLOCATED)
trace(" Already In Use\n");
goto EXIT;
}
/* We must call SetCooperativeLevel before calling CreateSoundBuffer */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
DXGetErrorString8(rc));
if (rc!=DS_OK)
goto EXIT;
/* Testing 3D buffers */
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_LOCHARDWARE|DSBCAPS_CTRL3D;
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK&&primary!=NULL,"IDirectSound_CreateSoundBuffer() failed to "
"create a hardware 3D primary buffer: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK&&primary!=NULL) {
ZeroMemory(&wfx, sizeof(wfx));
wfx.wFormatTag=WAVE_FORMAT_PCM;
wfx.nChannels=1;
wfx.wBitsPerSample=16;
wfx.nSamplesPerSec=44100;
wfx.nBlockAlign=wfx.nChannels*wfx.wBitsPerSample/8;
wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec;
bufdesc.lpwfxFormat=&wfx;
trace(" Testing a secondary buffer at %ldx%dx%d\n",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK&&secondary!=NULL,"IDirectSound_CreateSoundBuffer() "
"failed to create a secondary buffer: %s\n",DXGetErrorString8(rc));
if (rc==DS_OK&&secondary!=NULL) {
IKsPropertySet * pPropertySet=NULL;
rc=IDirectSoundBuffer_QueryInterface(secondary,
&IID_IKsPropertySet,
(void **)&pPropertySet);
/* it's not an error for this to fail */
if(rc==DS_OK) {
ULONG ulTypeSupport;
trace(" Supports property sets\n");
/* it's not an error for these to fail */
rc=IKsPropertySet_QuerySupport(pPropertySet,
&DSPROPSETID_VoiceManager,
0,&ulTypeSupport);
if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
KSPROPERTY_SUPPORT_SET)))
trace(" DSPROPSETID_VoiceManager supported\n");
else
trace(" DSPROPSETID_VoiceManager not supported\n");
rc=IKsPropertySet_QuerySupport(pPropertySet,
&DSPROPSETID_EAX20_ListenerProperties,0,&ulTypeSupport);
if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
KSPROPERTY_SUPPORT_SET)))
trace(" DSPROPSETID_EAX20_ListenerProperties "
"supported\n");
else
trace(" DSPROPSETID_EAX20_ListenerProperties not "
"supported\n");
rc=IKsPropertySet_QuerySupport(pPropertySet,
&DSPROPSETID_EAX20_BufferProperties,0,&ulTypeSupport);
if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
KSPROPERTY_SUPPORT_SET)))
trace(" DSPROPSETID_EAX20_BufferProperties supported\n");
else
trace(" DSPROPSETID_EAX20_BufferProperties not "
"supported\n");
rc=IKsPropertySet_QuerySupport(pPropertySet,
&DSPROPSETID_I3DL2_ListenerProperties,0,&ulTypeSupport);
if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
KSPROPERTY_SUPPORT_SET)))
trace(" DSPROPSETID_I3DL2_ListenerProperties "
"supported\n");
else
trace(" DSPROPSETID_I3DL2_ListenerProperties not "
"supported\n");
rc=IKsPropertySet_QuerySupport(pPropertySet,
&DSPROPSETID_I3DL2_BufferProperties,0,&ulTypeSupport);
if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
KSPROPERTY_SUPPORT_SET)))
trace(" DSPROPSETID_I3DL2_BufferProperties supported\n");
else
trace(" DSPROPSETID_I3DL2_BufferProperties not "
"supported\n");
rc=IKsPropertySet_QuerySupport(pPropertySet,
&DSPROPSETID_ZOOMFX_BufferProperties,0,&ulTypeSupport);
if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET|
KSPROPERTY_SUPPORT_SET)))
trace(" DSPROPSETID_ZOOMFX_BufferProperties "
"supported\n");
else
trace(" DSPROPSETID_ZOOMFX_BufferProperties not "
"supported\n");
ref=IKsPropertySet_Release(pPropertySet);
/* try a few common ones */
ok(ref==0,"IKsPropertySet_Release() secondary has %d "
"references, should have 0\n",ref);
} else
trace(" Doesn't support property sets\n");
ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d "
"references, should have 0\n",ref);
}
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
"should have 0\n",ref);
}
EXIT:
if (dso!=NULL) {
ref=IDirectSound_Release(dso);
ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
ref);
}
return 1;
}
static void propset_buffer_tests()
{
HRESULT rc;
rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
}
START_TEST(propset)
{
propset_private_tests();
propset_buffer_tests();
}

View file

@ -0,0 +1,27 @@
/*
* Copyright 2001 Ove Kaaven
*
* 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
*/
#define WINE_OLESELFREGISTER
#define WINE_FILEDESCRIPTION_STR "Wine DirectSound"
#define WINE_FILENAME_STR "dsound.dll"
#define WINE_FILEVERSION 5,3,0,900
#define WINE_FILEVERSION_STR "5.3.0.900"
#define WINE_PRODUCTVERSION 5,3,0,900
#define WINE_PRODUCTVERSION_STR "5.3"
#include "wine/wine_common_ver.rc"