Added support for multiple direct sound devices.

This commit is contained in:
Robert Reif 2003-03-15 00:54:11 +00:00 committed by Alexandre Julliard
parent 2e24a148bf
commit 89b469fefe
13 changed files with 556 additions and 193 deletions

View File

@ -84,7 +84,7 @@ static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) {
if (This->dsb) if (This->dsb)
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb); IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
else if (This->dscb) else if (This->dscb)
IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER8)This->dscb); IDirectSoundCaptureBuffer8_Release((LPDIRECTSOUNDCAPTUREBUFFER8)This->dscb);
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
return 0; return 0;
} }
@ -543,6 +543,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
assert(audiobytes1!=audiobytes2); assert(audiobytes1!=audiobytes2);
assert(lplpaudioptr1!=lplpaudioptr2); assert(lplpaudioptr1!=lplpaudioptr2);
EnterCriticalSection(&(This->lock));
if ((writebytes == This->buflen) && if ((writebytes == This->buflen) &&
((This->state == STATE_STARTING) || ((This->state == STATE_STARTING) ||
(This->state == STATE_PLAYING))) (This->state == STATE_PLAYING)))
@ -601,6 +603,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
} }
} }
} }
LeaveCriticalSection(&(This->lock));
return DS_OK; return DS_OK;
} }

View File

@ -20,8 +20,6 @@
*/ */
/* /*
* TODO: * TODO:
* Fix Enumerate for multiple sound devices.
* Handle device GUIDs properly.
* Implement DirectSoundFullDuplex support. * Implement DirectSoundFullDuplex support.
* Implement FX support. * Implement FX support.
*/ */
@ -97,6 +95,7 @@ DirectSoundCaptureCreate8(
LPDIRECTSOUNDCAPTURE* lplpDSC, LPDIRECTSOUNDCAPTURE* lplpDSC,
LPUNKNOWN pUnkOuter ) LPUNKNOWN pUnkOuter )
{ {
IDirectSoundCaptureImpl** ippDSC=(IDirectSoundCaptureImpl**)lplpDSC;
TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter); TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter);
if ( pUnkOuter ) { if ( pUnkOuter ) {
@ -110,43 +109,33 @@ DirectSoundCaptureCreate8(
} }
/* Default device? */ /* Default device? */
if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) || if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
IsEqualGUID(lpcGUID, &DSDEVID_DefaultCapture) || lpcGUID = &DSDEVID_DefaultCapture;
IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoiceCapture) ) {
IDirectSoundCaptureImpl** ippDSC=(IDirectSoundCaptureImpl**)lplpDSC;
*ippDSC = (IDirectSoundCaptureImpl*)HeapAlloc(GetProcessHeap(), *ippDSC = (IDirectSoundCaptureImpl*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureImpl)); HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureImpl));
if (*ippDSC == NULL) { if (*ippDSC == NULL) {
TRACE("couldn't allocate memory\n"); TRACE("couldn't allocate memory\n");
return DSERR_OUTOFMEMORY; return DSERR_OUTOFMEMORY;
}
else
{
ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC);
This->ref = 1;
This->state = STATE_STOPPED;
if (lpcGUID)
This->guid = *lpcGUID;
else
This->guid = GUID_NULL;
InitializeCriticalSection( &(This->lock) );
ICOM_VTBL(This) = &dscvt;
dsound_capture = This;
return IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE)This, lpcGUID );
}
} }
else
{
ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC);
FIXME( "Unknown GUID %s\n", debugstr_guid(lpcGUID) ); This->ref = 1;
*lplpDSC = NULL; This->state = STATE_STOPPED;
return DSERR_OUTOFMEMORY; InitializeCriticalSection( &(This->lock) );
ICOM_VTBL(This) = &dscvt;
dsound_capture = This;
if (GetDeviceID(lpcGUID, &This->guid) == DS_OK)
return IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE)This, &This->guid);
}
WARN("invalid GUID\n");
return DSERR_INVALIDPARAM;
} }
/*************************************************************************** /***************************************************************************
@ -163,8 +152,10 @@ DirectSoundCaptureEnumerateA(
LPDSENUMCALLBACKA lpDSEnumCallback, LPDSENUMCALLBACKA lpDSEnumCallback,
LPVOID lpContext) LPVOID lpContext)
{ {
WAVEINCAPSA wcaps;
unsigned devs, wid; unsigned devs, wid;
DSDRIVERDESC desc;
GUID guid;
int err;
TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext ); TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
@ -174,15 +165,37 @@ DirectSoundCaptureEnumerateA(
} }
devs = waveInGetNumDevs(); devs = waveInGetNumDevs();
if (devs > 0) {
if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
GUID temp;
for (wid = 0; wid < devs; ++wid) {
err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
if (err == DS_OK) {
if (IsEqualGUID( &guid, &temp ) ) {
err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
debugstr_guid(&DSDEVID_DefaultCapture),"Primary Sound Capture Driver",desc.szDrvName,lpContext);
if (lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, "Primary Sound Capture Driver", desc.szDrvName, lpContext) == FALSE)
return DS_OK;
}
}
}
}
}
}
for (wid = 0; wid < devs; ++wid) { for (wid = 0; wid < devs; ++wid) {
waveInGetDevCapsA(wid, &wcaps, sizeof(wcaps)); err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (lpDSEnumCallback) { if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(%s,\"WINE DirectSound\",\"%s\",%p)\n", err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
debugstr_guid(&DSDEVID_DefaultCapture),wcaps.szPname,lpContext); if (err == DS_OK) {
lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, "WINE DirectSound", TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
wcaps.szPname ,lpContext); debugstr_guid(&guid),desc.szDesc,desc.szDrvName,lpContext);
return DS_OK; if (lpDSEnumCallback(&guid, desc.szDesc, desc.szDrvName, lpContext) == FALSE)
} return DS_OK;
}
}
} }
return DS_OK; return DS_OK;
@ -202,9 +215,12 @@ DirectSoundCaptureEnumerateW(
LPDSENUMCALLBACKW lpDSEnumCallback, LPDSENUMCALLBACKW lpDSEnumCallback,
LPVOID lpContext) LPVOID lpContext)
{ {
WAVEINCAPSW wcaps;
unsigned devs, wid; unsigned devs, wid;
WCHAR desc[MAXPNAMELEN]; DSDRIVERDESC desc;
GUID guid;
int err;
WCHAR wDesc[MAXPNAMELEN];
WCHAR wName[MAXPNAMELEN];
TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext ); TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
@ -214,14 +230,45 @@ DirectSoundCaptureEnumerateW(
} }
devs = waveInGetNumDevs(); devs = waveInGetNumDevs();
if (devs > 0) {
if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
GUID temp;
for (wid = 0; wid < devs; ++wid) {
err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
if (err == DS_OK) {
if (IsEqualGUID( &guid, &temp ) ) {
err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
debugstr_guid(&DSDEVID_DefaultCapture),"Primary Sound Capture Driver",desc.szDrvName,lpContext);
MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
wDesc, sizeof(wDesc)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
wName, sizeof(wName)/sizeof(WCHAR) );
if (lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, wDesc, wName, lpContext) == FALSE)
return DS_OK;
}
}
}
}
}
}
for (wid = 0; wid < devs; ++wid) { for (wid = 0; wid < devs; ++wid) {
waveInGetDevCapsW(wid, &wcaps, sizeof(wcaps)); err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (lpDSEnumCallback) { if (err == DS_OK) {
MultiByteToWideChar( CP_ACP, 0, "WINE Sound Capture Driver", -1, err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
desc, sizeof(desc)/sizeof(WCHAR) ); if (err == DS_OK) {
lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, desc, wcaps.szPname ,lpContext); TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
return DS_OK; debugstr_guid(&DSDEVID_DefaultCapture),desc.szDesc,desc.szDrvName,lpContext);
} MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
wDesc, sizeof(wDesc)/sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
wName, sizeof(wName)/sizeof(WCHAR) );
if (lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, wDesc, wName, lpContext) == FALSE)
return DS_OK;
}
}
} }
return DS_OK; return DS_OK;
@ -402,7 +449,7 @@ IDirectSoundCaptureImpl_Initialize(
LPDIRECTSOUNDCAPTURE iface, LPDIRECTSOUNDCAPTURE iface,
LPCGUID lpcGUID ) LPCGUID lpcGUID )
{ {
HRESULT err = DS_OK; HRESULT err = DSERR_INVALIDPARAM;
unsigned wid, widn; unsigned wid, widn;
ICOM_THIS(IDirectSoundCaptureImpl,iface); ICOM_THIS(IDirectSoundCaptureImpl,iface);
TRACE("(%p)\n", This); TRACE("(%p)\n", This);
@ -427,8 +474,24 @@ IDirectSoundCaptureImpl_Initialize(
/* Get dsound configuration */ /* Get dsound configuration */
setup_dsound_options(); setup_dsound_options();
/* FIXME: should enumerate WINMM audio devices and find the one we want */ /* enumerate WINMM audio devices and find the one we want */
wid = 0; for (wid=0; wid<widn; wid++) {
GUID guid;
err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
if (err != DS_OK) {
WARN("waveInMessage failed; err=%lx\n",err);
return err;
}
if (IsEqualGUID( lpcGUID, &guid) ) {
err = DS_OK;
break;
}
}
if (err != DS_OK) {
WARN("invalid parameter\n");
return DSERR_INVALIDPARAM;
}
err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&(This->driver),0)); err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&(This->driver),0));
if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) { if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
@ -443,9 +506,6 @@ IDirectSoundCaptureImpl_Initialize(
/* Get driver description */ /* Get driver description */
if (This->driver) { if (This->driver) {
ERR("You have a sound card that is Direct Sound Capture capable but the driver is not finished. You can add a line to the wine config file in [dsound]: \"HardwareAcceleration\" = \"Emulation\" to force emulation mode.\n");
/* FIXME: remove this return to test driver */
return DSERR_NODRIVER;
TRACE("using DirectSound driver\n"); TRACE("using DirectSound driver\n");
err = IDsCaptureDriver_GetDriverDesc(This->driver, &(This->drvdesc)); err = IDsCaptureDriver_GetDriverDesc(This->driver, &(This->drvdesc));
if (err != DS_OK) { if (err != DS_OK) {
@ -484,11 +544,9 @@ IDirectSoundCaptureImpl_Initialize(
strncpy(This->drvdesc.szDrvName, wic.szPname, strncpy(This->drvdesc.szDrvName, wic.szPname,
sizeof(This->drvdesc.szDrvName)); sizeof(This->drvdesc.szDrvName));
This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
This->drvcaps.dwFormats = wic.dwFormats; This->drvcaps.dwFormats = wic.dwFormats;
This->drvcaps.dwChannels = wic.wChannels; This->drvcaps.dwChannels = wic.wChannels;
if (ds_emuldriver)
This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
} }
} }
} }
@ -656,7 +714,7 @@ IDirectSoundCaptureBufferImpl_QueryInterface(
return NO_ERROR; return NO_ERROR;
} }
FIXME("(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj); FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
return E_FAIL; return E_FAIL;
} }
@ -1226,7 +1284,7 @@ DirectSoundFullDuplexCreate8(
} }
*ippDSFD = (IDirectSoundFullDuplexImpl*)HeapAlloc(GetProcessHeap(), *ippDSFD = (IDirectSoundFullDuplexImpl*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl)); HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
if (*ippDSFD == NULL) { if (*ippDSFD == NULL) {
TRACE("couldn't allocate memory\n"); TRACE("couldn't allocate memory\n");

View File

@ -6,7 +6,7 @@
6 stdcall DirectSoundCaptureCreate(ptr ptr ptr) DirectSoundCaptureCreate8 6 stdcall DirectSoundCaptureCreate(ptr ptr ptr) DirectSoundCaptureCreate8
7 stdcall DirectSoundCaptureEnumerateA(ptr ptr) DirectSoundCaptureEnumerateA 7 stdcall DirectSoundCaptureEnumerateA(ptr ptr) DirectSoundCaptureEnumerateA
8 stdcall DirectSoundCaptureEnumerateW(ptr ptr) DirectSoundCaptureEnumerateW 8 stdcall DirectSoundCaptureEnumerateW(ptr ptr) DirectSoundCaptureEnumerateW
9 stub GetDeviceID 9 stdcall GetDeviceID(ptr ptr) GetDeviceID
10 stub DirectSoundFullDuplexCreate 10 stub DirectSoundFullDuplexCreate
11 stdcall DirectSoundCreate8(ptr ptr ptr) DirectSoundCreate8 11 stdcall DirectSoundCreate8(ptr ptr ptr) DirectSoundCreate8
12 stdcall DirectSoundCaptureCreate8(ptr ptr ptr) DirectSoundCaptureCreate8 12 stdcall DirectSoundCaptureCreate8(ptr ptr ptr) DirectSoundCaptureCreate8

View File

@ -116,23 +116,8 @@ int ds_hel_queue = DS_HEL_QUEUE;
int ds_snd_queue_max = DS_SND_QUEUE_MAX; int ds_snd_queue_max = DS_SND_QUEUE_MAX;
int ds_snd_queue_min = DS_SND_QUEUE_MIN; int ds_snd_queue_min = DS_SND_QUEUE_MIN;
int ds_hw_accel = DS_HW_ACCEL_FULL; int ds_hw_accel = DS_HW_ACCEL_FULL;
int ds_default_playback = 0;
/* int ds_default_capture = 0;
* Call the callback provided to DirectSoundEnumerateA.
*/
inline static void enumerate_devices(LPDSENUMCALLBACKA lpDSEnumCallback,
LPVOID lpContext)
{
if (lpDSEnumCallback != NULL) {
TRACE("calling lpDSEnumCallback(%s,\"WINE DirectSound\",\"sound\",%p)\n",
debugstr_guid(&DSDEVID_DefaultPlayback),lpContext);
lpDSEnumCallback((LPGUID)&DSDEVID_DefaultPlayback,
"WINE DirectSound", "sound", lpContext);
}
}
/* /*
* Get a config key from either the app-specific or the default config * Get a config key from either the app-specific or the default config
@ -211,6 +196,12 @@ void setup_dsound_options(void)
ds_hw_accel = DS_HW_ACCEL_EMULATION; 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 ); if (appkey) RegCloseKey( appkey );
RegCloseKey( hkey ); RegCloseKey( hkey );
@ -231,10 +222,56 @@ void setup_dsound_options(void)
ds_hw_accel==DS_HW_ACCEL_BASIC ? "Basic" : ds_hw_accel==DS_HW_ACCEL_BASIC ? "Basic" :
ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" : ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" :
"Unknown"); "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);
} }
/***************************************************************************
* GetDeviceId [DSOUND.2]
*
* Retrieves unique identifier of default device specified
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_INVALIDPARAM
*/
HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest)
{
if ( ( pGuidSrc == NULL) || (pGuidDest == NULL) ) {
WARN("invalid parameter\n");
return DSERR_INVALIDPARAM;
}
if ( IsEqualGUID( &DSDEVID_DefaultPlayback, pGuidSrc ) ||
IsEqualGUID( &DSDEVID_DefaultVoicePlayback, pGuidSrc ) ) {
GUID guid;
int err = mmErr(waveOutMessage((HWAVEOUT)ds_default_playback,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
if (err == DS_OK) {
memcpy(pGuidDest, &guid, sizeof(GUID));
return DS_OK;
}
}
if ( IsEqualGUID( &DSDEVID_DefaultCapture, pGuidSrc ) ||
IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) {
GUID guid;
int err = mmErr(waveInMessage((HWAVEIN)ds_default_capture,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
if (err == DS_OK) {
memcpy(pGuidDest, &guid, sizeof(GUID));
return DS_OK;
}
}
memcpy(pGuidDest, pGuidSrc, sizeof(GUID));
return DS_OK;
}
/*************************************************************************** /***************************************************************************
* DirectSoundEnumerateA [DSOUND.2] * DirectSoundEnumerateA [DSOUND.2]
* *
@ -245,25 +282,56 @@ void setup_dsound_options(void)
* Failure: DSERR_INVALIDPARAM * Failure: DSERR_INVALIDPARAM
*/ */
HRESULT WINAPI DirectSoundEnumerateA( HRESULT WINAPI DirectSoundEnumerateA(
LPDSENUMCALLBACKA lpDSEnumCallback, LPDSENUMCALLBACKA lpDSEnumCallback,
LPVOID lpContext) LPVOID lpContext)
{ {
WAVEOUTCAPSA wcaps; unsigned devs, wod;
unsigned devs, wod; DSDRIVERDESC desc;
GUID guid;
int err;
TRACE("lpDSEnumCallback = %p, lpContext = %p\n", TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
lpDSEnumCallback, lpContext); lpDSEnumCallback, lpContext);
devs = waveOutGetNumDevs(); if (lpDSEnumCallback == NULL) {
for (wod = 0; wod < devs; ++wod) { WARN("invalid parameter\n");
waveOutGetDevCapsA(wod, &wcaps, sizeof(wcaps)); return DSERR_INVALIDPARAM;
if (wcaps.dwSupport & WAVECAPS_DIRECTSOUND) { }
TRACE("- Device %u supports DirectSound\n", wod);
enumerate_devices(lpDSEnumCallback, lpContext); devs = waveOutGetNumDevs();
return DS_OK; if (devs > 0) {
} if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) {
} GUID temp;
return DS_OK; for (wod = 0; wod < devs; ++wod) {
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
if (err == DS_OK) {
if (IsEqualGUID( &guid, &temp ) ) {
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
debugstr_guid(&DSDEVID_DefaultPlayback),"Primary Sound Driver",desc.szDrvName,lpContext);
if (lpDSEnumCallback((LPGUID)&DSDEVID_DefaultPlayback, "Primary Sound Driver", desc.szDrvName, lpContext) == FALSE)
return DS_OK;
}
}
}
}
}
}
for (wod = 0; wod < devs; ++wod) {
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
if (err == DS_OK) {
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
if (err == DS_OK) {
TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
debugstr_guid(&guid),desc.szDesc,desc.szDrvName,lpContext);
if (lpDSEnumCallback(&guid, desc.szDesc, desc.szDrvName, lpContext) == FALSE)
return DS_OK;
}
}
}
return DS_OK;
} }
/*************************************************************************** /***************************************************************************
@ -588,36 +656,62 @@ static ICOM_VTABLE(IDirectSound8) dsvt =
/******************************************************************************* /*******************************************************************************
* DirectSoundCreate (DSOUND.1) * DirectSoundCreate (DSOUND.1)
*/ */
HRESULT WINAPI DirectSoundCreate8(REFGUID lpGUID,LPDIRECTSOUND8 *ppDS,IUnknown *pUnkOuter ) HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown *pUnkOuter )
{ {
IDirectSoundImpl** ippDS=(IDirectSoundImpl**)ppDS; IDirectSoundImpl** ippDS=(IDirectSoundImpl**)ppDS;
PIDSDRIVER drv = NULL; PIDSDRIVER drv = NULL;
unsigned wod, wodn; unsigned wod, wodn;
HRESULT err = DS_OK; HRESULT err = DSERR_INVALIDPARAM;
GUID devGuid;
if (lpGUID) TRACE("(%p,%p,%p)\n",lpcGUID,ippDS,pUnkOuter);
TRACE("(%p,%p,%p)\n",lpGUID,ippDS,pUnkOuter);
else
TRACE("DirectSoundCreate (%p)\n", ippDS);
if (ippDS == NULL) if (ippDS == NULL)
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
if (dsound) {
IDirectSound_AddRef((LPDIRECTSOUND)dsound);
*ippDS = dsound;
return DS_OK;
}
/* Get dsound configuration */ /* Get dsound configuration */
setup_dsound_options(); setup_dsound_options();
/* Default device? */
if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
lpcGUID = &DSDEVID_DefaultPlayback;
if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
WARN("invalid parameter\n");
return DSERR_INVALIDPARAM;
}
if (dsound && IsEqualGUID(&devGuid, &dsound->guid) ) {
ERR("dsound already opened\n");
if (IsEqualGUID(&devGuid, &dsound->guid) ) {
IDirectSound_AddRef((LPDIRECTSOUND)dsound);
*ippDS = dsound;
return DS_OK;
} else {
ERR("different dsound already opened\n");
}
}
/* Enumerate WINMM audio devices and find the one we want */ /* Enumerate WINMM audio devices and find the one we want */
wodn = waveOutGetNumDevs(); wodn = waveOutGetNumDevs();
if (!wodn) return DSERR_NODRIVER; if (!wodn) return DSERR_NODRIVER;
/* FIXME: How do we find the GUID of an audio device? */ for (wod=0; wod<wodn; wod++) {
wod = 0; /* start at the first audio device */ GUID guid;
err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
if (err != DS_OK) {
WARN("waveOutMessage failed; err=%lx\n",err);
return err;
}
if (IsEqualGUID( &devGuid, &guid) ) {
err = DS_OK;
break;
}
}
if (err != DS_OK) {
WARN("invalid parameter\n");
return DSERR_INVALIDPARAM;
}
/* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */ /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0); waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
@ -648,6 +742,7 @@ HRESULT WINAPI DirectSoundCreate8(REFGUID lpGUID,LPDIRECTSOUND8 *ppDS,IUnknown *
(*ippDS)->listener = NULL; (*ippDS)->listener = NULL;
(*ippDS)->prebuf = ds_snd_queue_max; (*ippDS)->prebuf = ds_snd_queue_max;
(*ippDS)->guid = devGuid;
/* Get driver description */ /* Get driver description */
if (drv) { if (drv) {

View File

@ -38,6 +38,8 @@ extern int ds_hel_queue;
extern int ds_snd_queue_max; extern int ds_snd_queue_max;
extern int ds_snd_queue_min; extern int ds_snd_queue_min;
extern int ds_hw_accel; extern int ds_hw_accel;
extern int ds_default_playback;
extern int ds_default_capture;
/***************************************************************************** /*****************************************************************************
* Predeclare the interface implementation structures * Predeclare the interface implementation structures
@ -62,6 +64,7 @@ struct IDirectSoundImpl
ICOM_VFIELD(IDirectSound8); ICOM_VFIELD(IDirectSound8);
DWORD ref; DWORD ref;
/* IDirectSoundImpl fields */ /* IDirectSoundImpl fields */
GUID guid;
PIDSDRIVER driver; PIDSDRIVER driver;
DSDRIVERDESC drvdesc; DSDRIVERDESC drvdesc;
DSDRIVERCAPS drvcaps; DSDRIVERCAPS drvcaps;

View File

@ -983,7 +983,9 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWOR
void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{ {
IDirectSoundImpl* This = (IDirectSoundImpl*)dwUser; IDirectSoundImpl* This = (IDirectSoundImpl*)dwUser;
TRACE("entering at %ld, msg=%08x\n", GetTickCount(), msg); TRACE("entering at %ld, msg=%08x(%s)\n", GetTickCount(), msg,
msg==MM_WOM_DONE ? "MM_WOM_DONE" : msg==MM_WOM_CLOSE ? "MM_WOM_CLOSE" :
msg==MM_WOM_OPEN ? "MM_WOM_OPEN" : "UNKNOWN");
if (msg == MM_WOM_DONE) { if (msg == MM_WOM_DONE) {
DWORD inq, mixq, fraglen, buflen, pwplay, playpos, mixpos; DWORD inq, mixq, fraglen, buflen, pwplay, playpos, mixpos;
if (This->pwqueue == (DWORD)-1) { if (This->pwqueue == (DWORD)-1) {

View File

@ -184,7 +184,8 @@ HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This)
{ {
DSOUND_PrimaryClose(This); DSOUND_PrimaryClose(This);
if (This->hwbuf) { if (This->hwbuf) {
IDsDriverBuffer_Release(This->hwbuf); if (IDsDriverBuffer_Release(This->hwbuf) == 0)
This->hwbuf = 0;
} else { } else {
unsigned c; unsigned c;
for (c=0; c<DS_HEL_FRAGS; c++) { for (c=0; c<DS_HEL_FRAGS; c++) {

View File

@ -488,6 +488,12 @@ UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1,
case DRV_QUERYDSOUNDIFACE: /* Wine-specific: Retrieve DirectSound interface */ case DRV_QUERYDSOUNDIFACE: /* Wine-specific: Retrieve DirectSound interface */
return MMDRV_Message(mld, uMsg, dwParam1, dwParam2, TRUE); return MMDRV_Message(mld, uMsg, dwParam1, dwParam2, TRUE);
case DRV_QUERYDSOUNDDESC: /* Wine-specific: Retrieve DirectSound driver description*/
return MMDRV_Message(mld, uMsg, dwParam1, dwParam2, TRUE);
case DRV_QUERYDSOUNDGUID: /* Wine-specific: Retrieve DirectSound driver GUID */
return MMDRV_Message(mld, uMsg, dwParam1, dwParam2, TRUE);
default: default:
WARN("Unknown call %04x\n", uMsg); WARN("Unknown call %04x\n", uMsg);
return MMSYSERR_INVALPARAM; return MMSYSERR_INVALPARAM;

View File

@ -4,7 +4,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
MODULE = winealsa.drv MODULE = winealsa.drv
IMPORTS = winmm user32 kernel32 ntdll IMPORTS = winmm user32 kernel32 ntdll
EXTRALIBS = @ALSALIBS@ EXTRALIBS = $(LIBUUID) @ALSALIBS@
LDDLLFLAGS = @LDDLLFLAGS@ LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o SYMBOLFILE = $(MODULE).tmp.o

View File

@ -149,13 +149,16 @@ typedef struct {
ALSA_MSG_RING msgRing; ALSA_MSG_RING msgRing;
/* DirectSound stuff */ /* DirectSound stuff */
DSDRIVERDESC ds_desc;
GUID ds_guid;
} WINE_WAVEOUT; } WINE_WAVEOUT;
static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV]; static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV];
static DWORD ALSA_WodNumDevs; static DWORD ALSA_WodNumDevs;
static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv); static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid);
/* These strings used only for tracing */ /* These strings used only for tracing */
#if 0 #if 0
@ -412,6 +415,9 @@ LONG ALSA_WaveInit(void)
wwo->caps.vDriverVersion = 0x0100; wwo->caps.vDriverVersion = 0x0100;
wwo->caps.dwFormats = 0x00000000; wwo->caps.dwFormats = 0x00000000;
wwo->caps.dwSupport = WAVECAPS_VOLUME; wwo->caps.dwSupport = WAVECAPS_VOLUME;
strcpy(wwo->ds_desc.szDesc, "WineALSA DirectSound Driver");
strcpy(wwo->ds_desc.szDrvName, "winealsa.drv");
wwo->ds_guid = DSDEVID_DefaultPlayback;
if (!wine_dlopen("libasound.so.2", RTLD_LAZY|RTLD_GLOBAL, NULL, 0)) if (!wine_dlopen("libasound.so.2", RTLD_LAZY|RTLD_GLOBAL, NULL, 0))
{ {
@ -1572,7 +1578,10 @@ DWORD WINAPI ALSA_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
case WODM_SETVOLUME: return wodSetVolume (wDevID, dwParam1); case WODM_SETVOLUME: return wodSetVolume (wDevID, dwParam1);
case WODM_RESTART: return wodRestart (wDevID); case WODM_RESTART: return wodRestart (wDevID);
case WODM_RESET: return wodReset (wDevID); case WODM_RESET: return wodReset (wDevID);
case DRV_QUERYDSOUNDIFACE: return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1); case DRV_QUERYDSOUNDIFACE: return wodDsCreate (wDevID, (PIDSDRIVER*)dwParam1);
case DRV_QUERYDSOUNDDESC: return wodDsDesc (wDevID, (PDSDRIVERDESC)dwParam1);
case DRV_QUERYDSOUNDGUID: return wodDsGuid (wDevID, (LPGUID)dwParam1);
default: default:
FIXME("unknown message %d!\n", wMsg); FIXME("unknown message %d!\n", wMsg);
} }
@ -1947,10 +1956,9 @@ static HRESULT WINAPI IDsDriverImpl_GetDriverDesc(PIDSDRIVER iface, PDSDRIVERDES
{ {
ICOM_THIS(IDsDriverImpl,iface); ICOM_THIS(IDsDriverImpl,iface);
TRACE("(%p,%p)\n",iface,pDesc); TRACE("(%p,%p)\n",iface,pDesc);
memcpy(pDesc, &(WOutDev[This->wDevID].ds_desc), sizeof(DSDRIVERDESC));
pDesc->dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT | pDesc->dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT |
DSDDESC_USESYSTEMMEMORY; DSDDESC_USESYSTEMMEMORY;
strcpy(pDesc->szDesc, "WineALSA DirectSound Driver");
strcpy(pDesc->szDrvName, "winealsa.drv");
pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode; pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode;
pDesc->wVxdId = 0; pDesc->wVxdId = 0;
pDesc->wReserved = 0; pDesc->wReserved = 0;
@ -2094,6 +2102,22 @@ static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
(*idrv)->primary = NULL; (*idrv)->primary = NULL;
return MMSYSERR_NOERROR; return MMSYSERR_NOERROR;
} }
static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
{
memcpy(desc, &(WOutDev[wDevID].ds_desc), sizeof(DSDRIVERDESC));
return MMSYSERR_NOERROR;
}
static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid)
{
TRACE("(%d,%p)\n",wDevID,pGuid);
memcpy(pGuid, &(WOutDev[wDevID].ds_guid), sizeof(GUID));
return MMSYSERR_NOERROR;
}
#endif #endif
#ifndef HAVE_ALSA #ifndef HAVE_ALSA

View File

@ -73,7 +73,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wave);
#ifdef HAVE_OSS #ifdef HAVE_OSS
#define MAX_WAVEDRV (3) #define MAX_WAVEDRV (6)
/* state diagram for waveOut writing: /* state diagram for waveOut writing:
* *
@ -145,8 +145,8 @@ typedef struct {
} OSS_MSG_RING; } OSS_MSG_RING;
typedef struct tagOSS_DEVICE { typedef struct tagOSS_DEVICE {
const char* dev_name; char dev_name[32];
const char* mixer_name; char mixer_name[32];
unsigned open_count; unsigned open_count;
WAVEOUTCAPSA out_caps; WAVEOUTCAPSA out_caps;
WAVEINCAPSA in_caps; WAVEINCAPSA in_caps;
@ -162,6 +162,11 @@ typedef struct tagOSS_DEVICE {
BOOL bTriggerSupport; BOOL bTriggerSupport;
BOOL bOutputEnabled; BOOL bOutputEnabled;
BOOL bInputEnabled; BOOL bInputEnabled;
DSDRIVERDESC ds_desc;
DSDRIVERCAPS ds_caps;
DSCDRIVERCAPS dsc_caps;
GUID ds_guid;
GUID dsc_guid;
} OSS_DEVICE; } OSS_DEVICE;
static OSS_DEVICE OSS_Devices[MAX_WAVEDRV]; static OSS_DEVICE OSS_Devices[MAX_WAVEDRV];
@ -226,6 +231,10 @@ static unsigned numInDev;
static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv); static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv);
static DWORD widDsCreate(UINT wDevID, PIDSCDRIVER* drv); static DWORD widDsCreate(UINT wDevID, PIDSCDRIVER* drv);
static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc);
static DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc);
static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid);
static DWORD widDsGuid(UINT wDevID, LPGUID pGuid);
/* These strings used only for tracing */ /* These strings used only for tracing */
static const char *wodPlayerCmdString[] = { static const char *wodPlayerCmdString[] = {
@ -258,6 +267,7 @@ static int getEnables(OSS_DEVICE *ossdev)
static DWORD OSS_RawOpenDevice(OSS_DEVICE* ossdev, int strict_format) static DWORD OSS_RawOpenDevice(OSS_DEVICE* ossdev, int strict_format)
{ {
int fd, val, rc; int fd, val, rc;
TRACE("(%p,%d)\n",ossdev,strict_format);
if ((fd = open(ossdev->dev_name, ossdev->open_access|O_NDELAY, 0)) == -1) if ((fd = open(ossdev->dev_name, ossdev->open_access|O_NDELAY, 0)) == -1)
{ {
@ -266,12 +276,20 @@ static DWORD OSS_RawOpenDevice(OSS_DEVICE* ossdev, int strict_format)
} }
fcntl(fd, F_SETFD, 1); /* set close on exec flag */ fcntl(fd, F_SETFD, 1); /* set close on exec flag */
/* turn full duplex on if it has been requested */ /* turn full duplex on if it has been requested */
if (ossdev->open_access == O_RDWR && ossdev->full_duplex) if (ossdev->open_access == O_RDWR && ossdev->full_duplex) {
ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); rc = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
if (rc != 0) {
ERR("ioctl(%s, SNDCTL_DSP_SETDUPLEX) failed (%s)\n", ossdev->dev_name, strerror(errno));
goto error;
}
}
if (ossdev->audio_fragment) if (ossdev->audio_fragment) {
{ rc = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &ossdev->audio_fragment);
ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &ossdev->audio_fragment); if (rc != 0) {
ERR("ioctl(%s, SNDCTL_DSP_SETFRAGMENT) failed (%s)\n", ossdev->dev_name, strerror(errno));
goto error;
}
} }
/* First size and stereo then samplerate */ /* First size and stereo then samplerate */
@ -306,8 +324,22 @@ static DWORD OSS_RawOpenDevice(OSS_DEVICE* ossdev, int strict_format)
} }
} }
ossdev->fd = fd; ossdev->fd = fd;
ossdev->bOutputEnabled = TRUE; /* OSS enables by default */
ossdev->bInputEnabled = TRUE; /* OSS enables by default */ if (ossdev->bTriggerSupport) {
int trigger;
rc = ioctl(fd, SNDCTL_DSP_GETTRIGGER, &trigger);
if (rc != 0) {
ERR("ioctl(%s, SNDCTL_DSP_GETTRIGGER) failed (%s)\n",
ossdev->dev_name, strerror(errno));
goto error;
}
ossdev->bOutputEnabled = ((trigger & PCM_ENABLE_OUTPUT) == PCM_ENABLE_OUTPUT);
ossdev->bInputEnabled = ((trigger & PCM_ENABLE_INPUT) == PCM_ENABLE_INPUT);
} else {
ossdev->bOutputEnabled = TRUE; /* OSS enables by default */
ossdev->bInputEnabled = TRUE; /* OSS enables by default */
}
return MMSYSERR_NOERROR; return MMSYSERR_NOERROR;
@ -328,6 +360,7 @@ static DWORD OSS_OpenDevice(OSS_DEVICE* ossdev, unsigned req_access,
int sample_rate, int stereo, int fmt) int sample_rate, int stereo, int fmt)
{ {
DWORD ret; DWORD ret;
TRACE("(%p,%u,%p,%d,%d,%d,%x)\n",ossdev,req_access,frag,strict_format,sample_rate,stereo,fmt);
if (ossdev->full_duplex && (req_access == O_RDONLY || req_access == O_WRONLY)) if (ossdev->full_duplex && (req_access == O_RDONLY || req_access == O_WRONLY))
req_access = O_RDWR; req_access = O_RDWR;
@ -354,6 +387,7 @@ static DWORD OSS_OpenDevice(OSS_DEVICE* ossdev, unsigned req_access,
WARN("Mismatch in access...\n"); WARN("Mismatch in access...\n");
return WAVERR_BADFORMAT; return WAVERR_BADFORMAT;
} }
/* FIXME: if really needed, we could do, in this case, on the fly /* FIXME: if really needed, we could do, in this case, on the fly
* PCM conversion (using the MSACM ad hoc driver) * PCM conversion (using the MSACM ad hoc driver)
*/ */
@ -390,6 +424,7 @@ static DWORD OSS_OpenDevice(OSS_DEVICE* ossdev, unsigned req_access,
*/ */
static void OSS_CloseDevice(OSS_DEVICE* ossdev) static void OSS_CloseDevice(OSS_DEVICE* ossdev)
{ {
TRACE("(%p)\n",ossdev);
if (ossdev->open_count>0) { if (ossdev->open_count>0) {
ossdev->open_count--; ossdev->open_count--;
} else { } else {
@ -456,10 +491,33 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
{ {
int rc,arg; int rc,arg;
int f,c,r; int f,c,r;
int mixer;
TRACE("(%p) %s\n", ossdev, ossdev->dev_name);
if (OSS_OpenDevice(ossdev, O_WRONLY, NULL, 0,-1,-1,-1) != 0) return FALSE; if (OSS_OpenDevice(ossdev, O_WRONLY, NULL, 0,-1,-1,-1) != 0) return FALSE;
ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0); ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
if ((mixer = open(ossdev->mixer_name, O_RDONLY|O_NDELAY)) >= 0) {
mixer_info info;
if (ioctl(mixer, SOUND_MIXER_INFO, &info) >= 0) {
close(mixer);
strncpy(ossdev->ds_desc.szDesc, info.name, sizeof(info.name));
strcpy(ossdev->ds_desc.szDrvName, "wineoss.drv");
strncpy(ossdev->out_caps.szPname, info.name, sizeof(info.name));
TRACE("%s\n", ossdev->ds_desc.szDesc);
} else {
ERR("%s: can't read info!\n", ossdev->mixer_name);
OSS_CloseDevice(ossdev);
close(mixer);
return FALSE;
}
} else {
ERR("%s: not found!\n", ossdev->mixer_name);
OSS_CloseDevice(ossdev);
return FALSE;
}
close(mixer);
/* FIXME: some programs compare this string against the content of the /* FIXME: some programs compare this string against the content of the
* registry for MM drivers. The names have to match in order for the * registry for MM drivers. The names have to match in order for the
* program to work (e.g. MS win9x mplayer.exe) * program to work (e.g. MS win9x mplayer.exe)
@ -471,8 +529,6 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
#else #else
ossdev->out_caps.wMid = 0x00FF; /* Manufac ID */ ossdev->out_caps.wMid = 0x00FF; /* Manufac ID */
ossdev->out_caps.wPid = 0x0001; /* Product ID */ ossdev->out_caps.wPid = 0x0001; /* Product ID */
/* strcpy(ossdev->out_caps.szPname, "OpenSoundSystem WAVOUT Driver");*/
strcpy(ossdev->out_caps.szPname, "CS4236/37/38");
#endif #endif
ossdev->out_caps.vDriverVersion = 0x0100; ossdev->out_caps.vDriverVersion = 0x0100;
ossdev->out_caps.wChannels = 1; ossdev->out_caps.wChannels = 1;
@ -480,6 +536,10 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
ossdev->out_caps.wReserved1 = 0; ossdev->out_caps.wReserved1 = 0;
ossdev->out_caps.dwSupport = WAVECAPS_VOLUME; ossdev->out_caps.dwSupport = WAVECAPS_VOLUME;
/* direct sound caps */
ossdev->ds_caps.dwFlags = 0;
ossdev->ds_caps.dwPrimaryBuffers = 1;
if (WINE_TRACE_ON(wave)) { if (WINE_TRACE_ON(wave)) {
/* Note that this only reports the formats supported by the hardware. /* Note that this only reports the formats supported by the hardware.
* The driver may support other formats and do the conversions in * The driver may support other formats and do the conversions in
@ -501,10 +561,14 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
arg=win_std_oss_fmts[f]; arg=win_std_oss_fmts[f];
rc=ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &arg); rc=ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &arg);
if (rc!=0 || arg!=win_std_oss_fmts[f]) { if (rc!=0 || arg!=win_std_oss_fmts[f]) {
TRACE("DSP_SAMPLESIZE: rc=%d returned 0x%x for 0x%x\n", TRACE("DSP_SAMPLESIZE: rc=%d returned %d for %d\n",
rc,arg,win_std_oss_fmts[f]); rc,arg,win_std_oss_fmts[f]);
continue; continue;
} }
if (f == 0)
ossdev->ds_caps.dwFlags |= DSCAPS_PRIMARY8BIT;
else if (f == 1)
ossdev->ds_caps.dwFlags |= DSCAPS_PRIMARY16BIT;
for (c=0;c<2;c++) { for (c=0;c<2;c++) {
arg=c; arg=c;
@ -513,9 +577,12 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
TRACE("DSP_STEREO: rc=%d returned %d for %d\n",rc,arg,c); TRACE("DSP_STEREO: rc=%d returned %d for %d\n",rc,arg,c);
continue; continue;
} }
if (c==1) { if (c == 0) {
ossdev->ds_caps.dwFlags |= DSCAPS_PRIMARYMONO;
} else if (c==1) {
ossdev->out_caps.wChannels=2; ossdev->out_caps.wChannels=2;
ossdev->out_caps.dwSupport|=WAVECAPS_LRVOLUME; ossdev->out_caps.dwSupport|=WAVECAPS_LRVOLUME;
ossdev->ds_caps.dwFlags |= DSCAPS_PRIMARYSTEREO;
} }
for (r=0;r<sizeof(win_std_rates)/sizeof(*win_std_rates);r++) { for (r=0;r<sizeof(win_std_rates)/sizeof(*win_std_rates);r++) {
@ -536,8 +603,11 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
} }
/* well, might as well use the DirectSound cap flag for something */ /* well, might as well use the DirectSound cap flag for something */
if ((arg & DSP_CAP_TRIGGER) && (arg & DSP_CAP_MMAP) && if ((arg & DSP_CAP_TRIGGER) && (arg & DSP_CAP_MMAP) &&
!(arg & DSP_CAP_BATCH)) !(arg & DSP_CAP_BATCH)) {
ossdev->out_caps.dwSupport |= WAVECAPS_DIRECTSOUND; ossdev->out_caps.dwSupport |= WAVECAPS_DIRECTSOUND;
} else {
ossdev->ds_caps.dwFlags |= DSCAPS_EMULDRIVER;
}
} }
OSS_CloseDevice(ossdev); OSS_CloseDevice(ossdev);
TRACE("out dwFormats = %08lX, dwSupport = %08lX\n", TRACE("out dwFormats = %08lX, dwSupport = %08lX\n",
@ -554,10 +624,31 @@ static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
{ {
int rc,arg; int rc,arg;
int f,c,r; int f,c,r;
int mixer;
TRACE("(%p) %s\n", ossdev, ossdev->dev_name);
if (OSS_OpenDevice(ossdev, O_RDONLY, NULL, 0,-1,-1,-1) != 0) return FALSE; if (OSS_OpenDevice(ossdev, O_RDONLY, NULL, 0,-1,-1,-1) != 0) return FALSE;
ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0); ioctl(ossdev->fd, SNDCTL_DSP_RESET, 0);
if ((mixer = open(ossdev->mixer_name, O_RDONLY|O_NDELAY)) >= 0) {
mixer_info info;
if (ioctl(mixer, SOUND_MIXER_INFO, &info) >= 0) {
close(mixer);
strncpy(ossdev->in_caps.szPname, info.name, sizeof(info.name));
TRACE("%s\n", ossdev->ds_desc.szDesc);
} else {
ERR("%s: can't read info!\n", ossdev->mixer_name);
OSS_CloseDevice(ossdev);
close(mixer);
return FALSE;
}
} else {
ERR("%s: not found!\n", ossdev->mixer_name);
OSS_CloseDevice(ossdev);
return FALSE;
}
close(mixer);
/* See comment in OSS_WaveOutInit */ /* See comment in OSS_WaveOutInit */
#ifdef EMULATE_SB16 #ifdef EMULATE_SB16
ossdev->in_caps.wMid = 0x0002; ossdev->in_caps.wMid = 0x0002;
@ -566,13 +657,18 @@ static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
#else #else
ossdev->in_caps.wMid = 0x00FF; /* Manufac ID */ ossdev->in_caps.wMid = 0x00FF; /* Manufac ID */
ossdev->in_caps.wPid = 0x0001; /* Product ID */ ossdev->in_caps.wPid = 0x0001; /* Product ID */
strcpy(ossdev->in_caps.szPname, "OpenSoundSystem WAVIN Driver");
#endif #endif
ossdev->in_caps.dwFormats = 0x00000000; ossdev->in_caps.dwFormats = 0x00000000;
ossdev->in_caps.wChannels = 1; ossdev->in_caps.wChannels = 1;
ossdev->in_caps.wReserved1 = 0; ossdev->in_caps.wReserved1 = 0;
ossdev->bTriggerSupport = FALSE; ossdev->bTriggerSupport = FALSE;
/* direct sound caps */
ossdev->dsc_caps.dwSize = sizeof(ossdev->dsc_caps);
ossdev->dsc_caps.dwFlags = 0;
ossdev->dsc_caps.dwFormats = 0x00000000;
ossdev->dsc_caps.dwChannels = 1;
if (WINE_TRACE_ON(wave)) { if (WINE_TRACE_ON(wave)) {
/* Note that this only reports the formats supported by the hardware. /* Note that this only reports the formats supported by the hardware.
* The driver may support other formats and do the conversions in * The driver may support other formats and do the conversions in
@ -602,6 +698,7 @@ static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
} }
if (c==1) { if (c==1) {
ossdev->in_caps.wChannels=2; ossdev->in_caps.wChannels=2;
ossdev->dsc_caps.dwChannels=2;
} }
for (r=0;r<sizeof(win_std_rates)/sizeof(*win_std_rates);r++) { for (r=0;r<sizeof(win_std_rates)/sizeof(*win_std_rates);r++) {
@ -610,6 +707,7 @@ static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
TRACE("DSP_SPEED: rc=%d returned %d for %dx%dx%d\n",rc,arg,win_std_rates[r],win_std_oss_fmts[f],c+1); TRACE("DSP_SPEED: rc=%d returned %d for %dx%dx%d\n",rc,arg,win_std_rates[r],win_std_oss_fmts[f],c+1);
if (rc==0 && NEAR_MATCH(arg,win_std_rates[r])) if (rc==0 && NEAR_MATCH(arg,win_std_rates[r]))
ossdev->in_caps.dwFormats|=win_std_formats[f][c][r]; ossdev->in_caps.dwFormats|=win_std_formats[f][c][r];
ossdev->dsc_caps.dwFormats|=win_std_formats[f][c][r];
} }
} }
} }
@ -619,8 +717,12 @@ static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
if (arg & DSP_CAP_TRIGGER) if (arg & DSP_CAP_TRIGGER)
ossdev->bTriggerSupport = TRUE; ossdev->bTriggerSupport = TRUE;
if ((arg & DSP_CAP_TRIGGER) && (arg & DSP_CAP_MMAP) && if ((arg & DSP_CAP_TRIGGER) && (arg & DSP_CAP_MMAP) &&
!(arg & DSP_CAP_BATCH)) !(arg & DSP_CAP_BATCH)) {
/* FIXME: enable the next statement if you want to work on the driver */
#if 0
ossdev->in_caps_support |= WAVECAPS_DIRECTSOUND; ossdev->in_caps_support |= WAVECAPS_DIRECTSOUND;
#endif
}
if ((arg & DSP_CAP_REALTIME) && !(arg & DSP_CAP_BATCH)) if ((arg & DSP_CAP_REALTIME) && !(arg & DSP_CAP_BATCH))
ossdev->in_caps_support |= WAVECAPS_SAMPLEACCURATE; ossdev->in_caps_support |= WAVECAPS_SAMPLEACCURATE;
} }
@ -637,6 +739,7 @@ static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
static void OSS_WaveFullDuplexInit(OSS_DEVICE* ossdev) static void OSS_WaveFullDuplexInit(OSS_DEVICE* ossdev)
{ {
int caps; int caps;
TRACE("(%p)\n",ossdev);
if (OSS_OpenDevice(ossdev, O_RDWR, NULL, 0,-1,-1,-1) != 0) return; if (OSS_OpenDevice(ossdev, O_RDWR, NULL, 0,-1,-1,-1) != 0) return;
if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0) if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0)
@ -646,6 +749,11 @@ static void OSS_WaveFullDuplexInit(OSS_DEVICE* ossdev)
OSS_CloseDevice(ossdev); OSS_CloseDevice(ossdev);
} }
#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;
/****************************************************************** /******************************************************************
* OSS_WaveInit * OSS_WaveInit
* *
@ -654,6 +762,7 @@ static void OSS_WaveFullDuplexInit(OSS_DEVICE* ossdev)
LONG OSS_WaveInit(void) LONG OSS_WaveInit(void)
{ {
int i; int i;
TRACE("()\n");
/* FIXME: only one device is supported */ /* FIXME: only one device is supported */
memset(&OSS_Devices, 0, sizeof(OSS_Devices)); memset(&OSS_Devices, 0, sizeof(OSS_Devices));
@ -661,12 +770,19 @@ LONG OSS_WaveInit(void)
* we should also be able to configure (bitmap) which devices we want to use... * we should also be able to configure (bitmap) which devices we want to use...
* - or even store the name of all drivers in our configuration * - or even store the name of all drivers in our configuration
*/ */
OSS_Devices[0].dev_name = "/dev/dsp"; for (i = 0; i < MAX_WAVEDRV; ++i)
OSS_Devices[0].mixer_name = "/dev/mixer"; {
OSS_Devices[1].dev_name = "/dev/dsp1"; if (i == 0) {
OSS_Devices[1].mixer_name = "/dev/mixer1"; sprintf((char *)OSS_Devices[i].dev_name, "/dev/dsp");
OSS_Devices[2].dev_name = "/dev/dsp2"; sprintf((char *)OSS_Devices[i].mixer_name, "/dev/mixer");
OSS_Devices[2].mixer_name = "/dev/mixer2"; } else {
sprintf((char *)OSS_Devices[i].dev_name, "/dev/dsp%d", i);
sprintf((char *)OSS_Devices[i].mixer_name, "/dev/mixer%d", i);
}
INIT_GUID(OSS_Devices[i].ds_guid, 0xe437ebb6, 0x534f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 + i);
INIT_GUID(OSS_Devices[i].dsc_guid, 0xe437ebb6, 0x534f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x80 + i);
}
/* start with output device */ /* start with output device */
for (i = 0; i < MAX_WAVEDRV; ++i) for (i = 0; i < MAX_WAVEDRV; ++i)
@ -882,7 +998,7 @@ static BOOL wodUpdatePlayedTotal(WINE_WAVEOUT* wwo, audio_buf_info* info)
if (!info) info = &dspspace; if (!info) info = &dspspace;
if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, info) < 0) { if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, info) < 0) {
ERR("ioctl can't 'SNDCTL_DSP_GETOSPACE' !\n"); ERR("ioctl(%s, SNDCTL_DSP_GETOSPACE) failed (%s)\n", wwo->ossdev->dev_name, strerror(errno));
return FALSE; return FALSE;
} }
wwo->dwPlayedTotal = wwo->dwWrittenTotal - (wwo->dwBufferSize - info->bytes); wwo->dwPlayedTotal = wwo->dwWrittenTotal - (wwo->dwBufferSize - info->bytes);
@ -1419,7 +1535,7 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
} }
/* Read output space info for future reference */ /* Read output space info for future reference */
if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
ERR("ioctl can't 'SNDCTL_DSP_GETOSPACE' !\n"); ERR("ioctl(%s, SNDCTL_DSP_GETOSPACE) failed (%s)\n", wwo->ossdev->dev_name, strerror(errno));
OSS_CloseDevice(wwo->ossdev); OSS_CloseDevice(wwo->ossdev);
wwo->state = WINE_WS_CLOSED; wwo->state = WINE_WS_CLOSED;
return MMSYSERR_NOTENABLED; return MMSYSERR_NOTENABLED;
@ -1731,7 +1847,7 @@ static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
return MMSYSERR_NOTENABLED; return MMSYSERR_NOTENABLED;
} }
if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) { if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {
WARN("unable to read mixer !\n"); WARN("ioctl(%s, SOUND_MIXER_READ_PCM) failed (%s)n", WOutDev[wDevID].ossdev->mixer_name, strerror(errno));
return MMSYSERR_NOTENABLED; return MMSYSERR_NOTENABLED;
} }
close(mixer); close(mixer);
@ -1764,7 +1880,7 @@ static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
return MMSYSERR_NOTENABLED; return MMSYSERR_NOTENABLED;
} }
if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) { if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {
WARN("unable to set mixer !\n"); WARN("ioctl(%s, SOUND_MIXER_WRITE_PCM) failed (%s)\n", WOutDev[wDevID].ossdev->mixer_name, strerror(errno));
return MMSYSERR_NOTENABLED; return MMSYSERR_NOTENABLED;
} else { } else {
TRACE("volume=%04x\n", (unsigned)volume); TRACE("volume=%04x\n", (unsigned)volume);
@ -1808,7 +1924,9 @@ DWORD WINAPI OSS_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
case WODM_RESTART: return wodRestart (wDevID); case WODM_RESTART: return wodRestart (wDevID);
case WODM_RESET: return wodReset (wDevID); case WODM_RESET: return wodReset (wDevID);
case DRV_QUERYDSOUNDIFACE: return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1); case DRV_QUERYDSOUNDIFACE: return wodDsCreate (wDevID, (PIDSDRIVER*)dwParam1);
case DRV_QUERYDSOUNDDESC: return wodDsDesc (wDevID, (PDSDRIVERDESC)dwParam1);
case DRV_QUERYDSOUNDGUID: return wodDsGuid (wDevID, (LPGUID)dwParam1);
default: default:
FIXME("unknown message %d!\n", wMsg); FIXME("unknown message %d!\n", wMsg);
} }
@ -1845,6 +1963,7 @@ struct IDsDriverBufferImpl
static HRESULT DSDB_MapPrimary(IDsDriverBufferImpl *dsdb) static HRESULT DSDB_MapPrimary(IDsDriverBufferImpl *dsdb)
{ {
WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]); WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]);
TRACE("(%p)\n",dsdb);
if (!wwo->mapping) { if (!wwo->mapping) {
wwo->mapping = mmap(NULL, wwo->maplen, PROT_WRITE, MAP_SHARED, wwo->mapping = mmap(NULL, wwo->maplen, PROT_WRITE, MAP_SHARED,
wwo->ossdev->fd, 0); wwo->ossdev->fd, 0);
@ -1887,9 +2006,10 @@ static HRESULT DSDB_MapPrimary(IDsDriverBufferImpl *dsdb)
static HRESULT DSDB_UnmapPrimary(IDsDriverBufferImpl *dsdb) static HRESULT DSDB_UnmapPrimary(IDsDriverBufferImpl *dsdb)
{ {
WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]); WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]);
TRACE("(%p)\n",dsdb);
if (wwo->mapping) { if (wwo->mapping) {
if (munmap(wwo->mapping, wwo->maplen) < 0) { if (munmap(wwo->mapping, wwo->maplen) < 0) {
ERR("(%p): Could not unmap sound device (errno=%d)\n", dsdb, errno); ERR("(%p): Could not unmap sound device (%s)\n", dsdb, strerror(errno));
return DSERR_GENERIC; return DSERR_GENERIC;
} }
wwo->mapping = NULL; wwo->mapping = NULL;
@ -1908,19 +2028,25 @@ static HRESULT WINAPI IDsDriverBufferImpl_QueryInterface(PIDSDRIVERBUFFER iface,
static ULONG WINAPI IDsDriverBufferImpl_AddRef(PIDSDRIVERBUFFER iface) static ULONG WINAPI IDsDriverBufferImpl_AddRef(PIDSDRIVERBUFFER iface)
{ {
ICOM_THIS(IDsDriverBufferImpl,iface); ICOM_THIS(IDsDriverBufferImpl,iface);
TRACE("(%p)\n",This);
This->ref++; This->ref++;
TRACE("ref=%ld\n",This->ref);
return This->ref; return This->ref;
} }
static ULONG WINAPI IDsDriverBufferImpl_Release(PIDSDRIVERBUFFER iface) static ULONG WINAPI IDsDriverBufferImpl_Release(PIDSDRIVERBUFFER iface)
{ {
ICOM_THIS(IDsDriverBufferImpl,iface); ICOM_THIS(IDsDriverBufferImpl,iface);
if (--This->ref) TRACE("(%p)\n",This);
if (--This->ref) {
TRACE("ref=%ld\n",This->ref);
return This->ref; return This->ref;
}
if (This == This->drv->primary) if (This == This->drv->primary)
This->drv->primary = NULL; This->drv->primary = NULL;
DSDB_UnmapPrimary(This); DSDB_UnmapPrimary(This);
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
TRACE("ref=0\n");
return 0; return 0;
} }
@ -1995,7 +2121,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,
return DSERR_UNINITIALIZED; return DSERR_UNINITIALIZED;
} }
if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_GETOPTR) failed (%s)\n", WOutDev[This->drv->wDevID].ossdev->dev_name, strerror(errno));
return DSERR_GENERIC; return DSERR_GENERIC;
} }
ptr = info.ptr & ~3; /* align the pointer, just in case */ ptr = info.ptr & ~3; /* align the pointer, just in case */
@ -2021,7 +2147,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_Play(PIDSDRIVERBUFFER iface, DWORD dwR
WOutDev[This->drv->wDevID].ossdev->bOutputEnabled = TRUE; WOutDev[This->drv->wDevID].ossdev->bOutputEnabled = TRUE;
enable = getEnables(WOutDev[This->drv->wDevID].ossdev); enable = getEnables(WOutDev[This->drv->wDevID].ossdev);
if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) { if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)\n",WOutDev[This->drv->wDevID].ossdev->dev_name, strerror(errno));
WOutDev[This->drv->wDevID].ossdev->bOutputEnabled = FALSE; WOutDev[This->drv->wDevID].ossdev->bOutputEnabled = FALSE;
return DSERR_GENERIC; return DSERR_GENERIC;
} }
@ -2037,13 +2163,13 @@ static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface)
WOutDev[This->drv->wDevID].ossdev->bOutputEnabled = FALSE; WOutDev[This->drv->wDevID].ossdev->bOutputEnabled = FALSE;
enable = getEnables(WOutDev[This->drv->wDevID].ossdev); enable = getEnables(WOutDev[This->drv->wDevID].ossdev);
if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) { if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)\n", WOutDev[This->drv->wDevID].ossdev->dev_name, strerror(errno));
return DSERR_GENERIC; return DSERR_GENERIC;
} }
#if 0 #if 0
/* the play position must be reset to the beginning of the buffer */ /* the play position must be reset to the beginning of the buffer */
if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_RESET, 0) < 0) { if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_RESET, 0) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_RESET) failed (%s)\n", WOutDev[This->drv->wDevID].ossdev->dev_name, strerror(errno));
return DSERR_GENERIC; return DSERR_GENERIC;
} }
#endif #endif
@ -2081,16 +2207,22 @@ static HRESULT WINAPI IDsDriverImpl_QueryInterface(PIDSDRIVER iface, REFIID riid
static ULONG WINAPI IDsDriverImpl_AddRef(PIDSDRIVER iface) static ULONG WINAPI IDsDriverImpl_AddRef(PIDSDRIVER iface)
{ {
ICOM_THIS(IDsDriverImpl,iface); ICOM_THIS(IDsDriverImpl,iface);
TRACE("(%p)\n",This);
This->ref++; This->ref++;
TRACE("ref=%ld\n",This->ref);
return This->ref; return This->ref;
} }
static ULONG WINAPI IDsDriverImpl_Release(PIDSDRIVER iface) static ULONG WINAPI IDsDriverImpl_Release(PIDSDRIVER iface)
{ {
ICOM_THIS(IDsDriverImpl,iface); ICOM_THIS(IDsDriverImpl,iface);
if (--This->ref) TRACE("(%p)\n",This);
if (--This->ref) {
TRACE("ref=%ld\n",This->ref);
return This->ref; return This->ref;
}
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
TRACE("ref=0\n");
return 0; return 0;
} }
@ -2098,10 +2230,12 @@ static HRESULT WINAPI IDsDriverImpl_GetDriverDesc(PIDSDRIVER iface, PDSDRIVERDES
{ {
ICOM_THIS(IDsDriverImpl,iface); ICOM_THIS(IDsDriverImpl,iface);
TRACE("(%p,%p)\n",iface,pDesc); TRACE("(%p,%p)\n",iface,pDesc);
pDesc->dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT |
/* copy version from driver */
memcpy(pDesc, &(WOutDev[This->wDevID].ossdev->ds_desc), sizeof(DSDRIVERDESC));
pDesc->dwFlags |= DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT |
DSDDESC_USESYSTEMMEMORY | DSDDESC_DONTNEEDPRIMARYLOCK; DSDDESC_USESYSTEMMEMORY | DSDDESC_DONTNEEDPRIMARYLOCK;
strcpy(pDesc->szDesc,"WineOSS DirectSound Driver");
strcpy(pDesc->szDrvName,"wineoss.drv");
pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode; pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode;
pDesc->wVxdId = 0; pDesc->wVxdId = 0;
pDesc->wReserved = 0; pDesc->wReserved = 0;
@ -2126,7 +2260,7 @@ static HRESULT WINAPI IDsDriverImpl_Open(PIDSDRIVER iface)
WOutDev[This->wDevID].ossdev->bOutputEnabled = FALSE; WOutDev[This->wDevID].ossdev->bOutputEnabled = FALSE;
enable = getEnables(WOutDev[This->wDevID].ossdev); enable = getEnables(WOutDev[This->wDevID].ossdev);
if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) { if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)\n",WOutDev[This->wDevID].ossdev->dev_name, strerror(errno));
return DSERR_GENERIC; return DSERR_GENERIC;
} }
return DS_OK; return DS_OK;
@ -2145,15 +2279,9 @@ static HRESULT WINAPI IDsDriverImpl_Close(PIDSDRIVER iface)
static HRESULT WINAPI IDsDriverImpl_GetCaps(PIDSDRIVER iface, PDSDRIVERCAPS pCaps) static HRESULT WINAPI IDsDriverImpl_GetCaps(PIDSDRIVER iface, PDSDRIVERCAPS pCaps)
{ {
/* ICOM_THIS(IDsDriverImpl,iface); */ ICOM_THIS(IDsDriverImpl,iface);
TRACE("(%p,%p)\n",iface,pCaps); TRACE("(%p,%p)\n",iface,pCaps);
memset(pCaps, 0, sizeof(*pCaps)); memcpy(pCaps, &(WOutDev[This->wDevID].ossdev->ds_caps), sizeof(DSDRIVERCAPS));
/* FIXME: need to check actual capabilities */
pCaps->dwFlags = DSCAPS_PRIMARYMONO | DSCAPS_PRIMARYSTEREO |
DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARY16BIT;
pCaps->dwPrimaryBuffers = 1;
/* the other fields only apply to secondary buffers, which we don't support
* (unless we want to mess with wavetable synthesizers and MIDI) */
return DS_OK; return DS_OK;
} }
@ -2169,8 +2297,8 @@ static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface,
HRESULT err; HRESULT err;
audio_buf_info info; audio_buf_info info;
int enable = 0; int enable = 0;
TRACE("(%p,%p,%lx,%lx)\n",iface,pwfx,dwFlags,dwCardAddress); TRACE("(%p,%p,%lx,%lx)\n",iface,pwfx,dwFlags,dwCardAddress);
/* we only support primary buffers */ /* we only support primary buffers */
if (!(dwFlags & DSBCAPS_PRIMARYBUFFER)) if (!(dwFlags & DSBCAPS_PRIMARYBUFFER))
return DSERR_UNSUPPORTED; return DSERR_UNSUPPORTED;
@ -2188,7 +2316,7 @@ static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface,
/* check how big the DMA buffer is now */ /* check how big the DMA buffer is now */
if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_GETOSPACE) failed (%s)\n", WOutDev[This->wDevID].ossdev->dev_name, strerror(errno));
HeapFree(GetProcessHeap(),0,*ippdsdb); HeapFree(GetProcessHeap(),0,*ippdsdb);
*ippdsdb = NULL; *ippdsdb = NULL;
return DSERR_GENERIC; return DSERR_GENERIC;
@ -2211,7 +2339,7 @@ static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface,
WOutDev[This->wDevID].ossdev->bOutputEnabled = FALSE; WOutDev[This->wDevID].ossdev->bOutputEnabled = FALSE;
enable = getEnables(WOutDev[This->wDevID].ossdev); enable = getEnables(WOutDev[This->wDevID].ossdev);
if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) { if (ioctl(WOutDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)\n", WOutDev[This->wDevID].ossdev->dev_name, strerror(errno));
return DSERR_GENERIC; return DSERR_GENERIC;
} }
@ -2246,6 +2374,7 @@ static ICOM_VTABLE(IDsDriver) dsdvt =
static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv) static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
{ {
IDsDriverImpl** idrv = (IDsDriverImpl**)drv; IDsDriverImpl** idrv = (IDsDriverImpl**)drv;
TRACE("(%d,%p)\n",wDevID,drv);
/* the HAL isn't much better than the HEL if we can't do mmap() */ /* the HAL isn't much better than the HEL if we can't do mmap() */
if (!(WOutDev[wDevID].ossdev->out_caps.dwSupport & WAVECAPS_DIRECTSOUND)) { if (!(WOutDev[wDevID].ossdev->out_caps.dwSupport & WAVECAPS_DIRECTSOUND)) {
@ -2266,6 +2395,20 @@ static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
return MMSYSERR_NOERROR; return MMSYSERR_NOERROR;
} }
static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
{
TRACE("(%d,%p)\n",wDevID,desc);
memcpy(desc, &(WOutDev[wDevID].ossdev->ds_desc), sizeof(DSDRIVERDESC));
return MMSYSERR_NOERROR;
}
static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid)
{
TRACE("(%d,%p)\n",wDevID,pGuid);
memcpy(pGuid, &(WOutDev[wDevID].ossdev->ds_guid), sizeof(GUID));
return MMSYSERR_NOERROR;
}
/*======================================================================* /*======================================================================*
* Low level WAVE IN implementation * * Low level WAVE IN implementation *
*======================================================================*/ *======================================================================*/
@ -2343,7 +2486,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
wwi->ossdev->bInputEnabled = FALSE; wwi->ossdev->bInputEnabled = FALSE;
enable = getEnables(wwi->ossdev); enable = getEnables(wwi->ossdev);
if (ioctl(wwi->ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) if (ioctl(wwi->ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0)
ERR("ioctl(SNDCTL_DSP_SETTRIGGER) failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)\n", wwi->ossdev->dev_name, strerror(errno));
/* the soundblaster live needs a micro wake to get its recording started /* the soundblaster live needs a micro wake to get its recording started
* (or GETISPACE will have 0 frags all the time) * (or GETISPACE will have 0 frags all the time)
@ -2499,7 +2642,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
enable = getEnables(wwi->ossdev); enable = getEnables(wwi->ossdev);
if (ioctl(wwi->ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) { if (ioctl(wwi->ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
wwi->ossdev->bInputEnabled = FALSE; wwi->ossdev->bInputEnabled = FALSE;
ERR("ioctl(SNDCTL_DSP_SETTRIGGER) failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)\n", wwi->ossdev->dev_name, strerror(errno));
} }
} }
else else
@ -2650,7 +2793,7 @@ static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
ioctl(wwi->ossdev->fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size); ioctl(wwi->ossdev->fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
if (fragment_size == -1) { if (fragment_size == -1) {
WARN("IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n"); WARN("ioctl(%s, SNDCTL_DSP_GETBLKSIZE) failed (%s)\n", wwi->ossdev->dev_name, strerror(errno));
OSS_CloseDevice(wwi->ossdev); OSS_CloseDevice(wwi->ossdev);
wwi->state = WINE_WS_CLOSED; wwi->state = WINE_WS_CLOSED;
return MMSYSERR_NOTENABLED; return MMSYSERR_NOTENABLED;
@ -2899,6 +3042,8 @@ DWORD WINAPI OSS_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
case WIDM_START: return widStart (wDevID); case WIDM_START: return widStart (wDevID);
case WIDM_STOP: return widStop (wDevID); case WIDM_STOP: return widStop (wDevID);
case DRV_QUERYDSOUNDIFACE: return widDsCreate (wDevID, (PIDSCDRIVER*)dwParam1); case DRV_QUERYDSOUNDIFACE: return widDsCreate (wDevID, (PIDSCDRIVER*)dwParam1);
case DRV_QUERYDSOUNDDESC: return widDsDesc (wDevID, (PDSDRIVERDESC)dwParam1);
case DRV_QUERYDSOUNDGUID: return widDsGuid (wDevID, (LPGUID)dwParam1);
default: default:
FIXME("unknown message %u!\n", wMsg); FIXME("unknown message %u!\n", wMsg);
} }
@ -3047,7 +3192,7 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_GetPosition(PIDSCDRIVERBUFFER i
return DSERR_UNINITIALIZED; return DSERR_UNINITIALIZED;
} }
if (ioctl(WInDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { if (ioctl(WInDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
ERR("ioctl failed (%s)\n", strerror(errno)); ERR("ioctl(%s, SNDCTL_DSP_GETIPTR) failed (%s)\n", WInDev[This->drv->wDevID].ossdev->dev_name, strerror(errno));
return DSERR_GENERIC; return DSERR_GENERIC;
} }
ptr = info.ptr & ~3; /* align the pointer, just in case */ ptr = info.ptr & ~3; /* align the pointer, just in case */
@ -3080,7 +3225,7 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_Start(PIDSCDRIVERBUFFER iface,
WInDev[This->drv->wDevID].ossdev->bInputEnabled = TRUE; WInDev[This->drv->wDevID].ossdev->bInputEnabled = TRUE;
enable = getEnables(WInDev[This->drv->wDevID].ossdev); enable = getEnables(WInDev[This->drv->wDevID].ossdev);
if (ioctl(WInDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) { if (ioctl(WInDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)\n", WInDev[This->drv->wDevID].ossdev->dev_name, strerror(errno));
WInDev[This->drv->wDevID].ossdev->bInputEnabled = FALSE; WInDev[This->drv->wDevID].ossdev->bInputEnabled = FALSE;
return DSERR_GENERIC; return DSERR_GENERIC;
} }
@ -3096,7 +3241,7 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_Stop(PIDSCDRIVERBUFFER iface)
WInDev[This->drv->wDevID].ossdev->bInputEnabled = FALSE; WInDev[This->drv->wDevID].ossdev->bInputEnabled = FALSE;
enable = getEnables(WInDev[This->drv->wDevID].ossdev); enable = getEnables(WInDev[This->drv->wDevID].ossdev);
if (ioctl(WInDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) { if (ioctl(WInDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)\n", WInDev[This->drv->wDevID].ossdev->dev_name, strerror(errno));
return DSERR_GENERIC; return DSERR_GENERIC;
} }
@ -3139,16 +3284,22 @@ static HRESULT WINAPI IDsCaptureDriverImpl_QueryInterface(PIDSCDRIVER iface, REF
static ULONG WINAPI IDsCaptureDriverImpl_AddRef(PIDSCDRIVER iface) static ULONG WINAPI IDsCaptureDriverImpl_AddRef(PIDSCDRIVER iface)
{ {
ICOM_THIS(IDsCaptureDriverImpl,iface); ICOM_THIS(IDsCaptureDriverImpl,iface);
TRACE("(%p)\n",This);
This->ref++; This->ref++;
TRACE("ref=%ld\n",This->ref);
return This->ref; return This->ref;
} }
static ULONG WINAPI IDsCaptureDriverImpl_Release(PIDSCDRIVER iface) static ULONG WINAPI IDsCaptureDriverImpl_Release(PIDSCDRIVER iface)
{ {
ICOM_THIS(IDsCaptureDriverImpl,iface); ICOM_THIS(IDsCaptureDriverImpl,iface);
if (--This->ref) TRACE("(%p)\n",This);
if (--This->ref) {
TRACE("ref=%ld\n",This->ref);
return This->ref; return This->ref;
}
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
TRACE("ref=0\n");
return 0; return 0;
} }
@ -3162,11 +3313,12 @@ static HRESULT WINAPI IDsCaptureDriverImpl_GetDriverDesc(PIDSCDRIVER iface, PDSD
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
pDesc->dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT | /* copy version from driver */
memcpy(pDesc, &(WInDev[This->wDevID].ossdev->ds_desc), sizeof(DSDRIVERDESC));
pDesc->dwFlags |= DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT |
DSDDESC_USESYSTEMMEMORY | DSDDESC_DONTNEEDPRIMARYLOCK | DSDDESC_USESYSTEMMEMORY | DSDDESC_DONTNEEDPRIMARYLOCK |
DSDDESC_DONTNEEDSECONDARYLOCK; DSDDESC_DONTNEEDSECONDARYLOCK;
strcpy(pDesc->szDesc,"WineOSS DirectSound Driver");
strcpy(pDesc->szDrvName,"wineoss.drv");
pDesc->dnDevNode = WInDev[This->wDevID].waveDesc.dnDevNode; pDesc->dnDevNode = WInDev[This->wDevID].waveDesc.dnDevNode;
pDesc->wVxdId = 0; pDesc->wVxdId = 0;
pDesc->wReserved = 0; pDesc->wReserved = 0;
@ -3203,16 +3355,7 @@ static HRESULT WINAPI IDsCaptureDriverImpl_GetCaps(PIDSCDRIVER iface, PDSCDRIVER
{ {
ICOM_THIS(IDsCaptureDriverImpl,iface); ICOM_THIS(IDsCaptureDriverImpl,iface);
TRACE("(%p,%p)\n",This,pCaps); TRACE("(%p,%p)\n",This,pCaps);
memcpy(pCaps, &(WInDev[This->wDevID].ossdev->dsc_caps), sizeof(DSCDRIVERCAPS));
if ( !pCaps || (pCaps->dwSize != sizeof(*pCaps)) ) {
TRACE("invalid parameter\n");
return DSERR_INVALIDPARAM;
}
pCaps->dwFlags = 0;
pCaps->dwChannels = WInDev[This->wDevID].ossdev->in_caps.wChannels;
pCaps->dwFormats = WInDev[This->wDevID].ossdev->in_caps.dwFormats;
return DS_OK; return DS_OK;
} }
@ -3263,7 +3406,7 @@ static HRESULT WINAPI IDsCaptureDriverImpl_CreateCaptureBuffer(PIDSCDRIVER iface
/* check how big the DMA buffer is now */ /* check how big the DMA buffer is now */
if (ioctl(WInDev[This->wDevID].ossdev->fd, SNDCTL_DSP_GETISPACE, &info) < 0) { if (ioctl(WInDev[This->wDevID].ossdev->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
ERR("ioctl failed (%s)\n", strerror(errno)); ERR("ioctl(%s, SNDCTL_DSP_GETISPACE) failed (%s)\n", WInDev[This->wDevID].ossdev->dev_name, strerror(errno));
HeapFree(GetProcessHeap(),0,*ippdscdb); HeapFree(GetProcessHeap(),0,*ippdscdb);
*ippdscdb = NULL; *ippdscdb = NULL;
return DSERR_GENERIC; return DSERR_GENERIC;
@ -3286,7 +3429,7 @@ static HRESULT WINAPI IDsCaptureDriverImpl_CreateCaptureBuffer(PIDSCDRIVER iface
WInDev[This->wDevID].ossdev->bInputEnabled = FALSE; WInDev[This->wDevID].ossdev->bInputEnabled = FALSE;
enable = getEnables(WInDev[This->wDevID].ossdev); enable = getEnables(WInDev[This->wDevID].ossdev);
if (ioctl(WInDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) { if (ioctl(WInDev[This->wDevID].ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
ERR("ioctl failed (%d)\n", errno); ERR("ioctl(%s, SNDCTL_DSP_SETTRIGGER) failed (%s)\n", WInDev[This->wDevID].ossdev->dev_name, strerror(errno));
return DSERR_GENERIC; return DSERR_GENERIC;
} }
@ -3332,6 +3475,21 @@ static DWORD widDsCreate(UINT wDevID, PIDSCDRIVER* drv)
return MMSYSERR_NOERROR; return MMSYSERR_NOERROR;
} }
static DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc)
{
memcpy(desc, &(WInDev[wDevID].ossdev->ds_desc), sizeof(DSDRIVERDESC));
return MMSYSERR_NOERROR;
}
static DWORD widDsGuid(UINT wDevID, LPGUID pGuid)
{
TRACE("(%d,%p)\n",wDevID,pGuid);
memcpy(pGuid, &(WInDev[wDevID].ossdev->dsc_guid), sizeof(GUID));
return MMSYSERR_NOERROR;
}
#else /* !HAVE_OSS */ #else /* !HAVE_OSS */
/************************************************************************** /**************************************************************************

View File

@ -267,6 +267,16 @@ WINE REGISTRY Version 2
;"SndQueueMax" = "28" ;"SndQueueMax" = "28"
;; Min number of fragments to prebuffer ;; Min number of fragments to prebuffer
;"SndQueueMin" = "12" ;"SndQueueMin" = "12"
;; Forces emulation mode (using wave api)
;"HardwareAcceleration" = "Emulation"
;; Sets default playback device (0 - number of devices - 1)
;"DefaultPlayback" = "0" ; use first device (/dev/dsp)
;"DefaultPlayback" = "1" ; use second device (/dev/dsp1)
;"DefaultPlayback" = "2" ; use third device (/dev/dsp2)
;; Sets default capture device (0 - number of devices - 1)
;"DefaultCapture" = "0" ; use first device (/dev/dsp)
;"DefaultCapture" = "1" ; use second device (/dev/dsp1)
;"DefaultCapture" = "2" ; use third device (/dev/dsp2)
[Network] [Network]
;; Use the DNS (Unix) host name always as NetBIOS "ComputerName" (boolean, default "Y"). ;; Use the DNS (Unix) host name always as NetBIOS "ComputerName" (boolean, default "Y").

View File

@ -81,6 +81,8 @@ typedef struct {
#define DRV_QUERYMAPPABLE (DRV_RESERVED + 5) #define DRV_QUERYMAPPABLE (DRV_RESERVED + 5)
#ifdef __WINESRC__ #ifdef __WINESRC__
#define DRV_QUERYDSOUNDIFACE (DRV_RESERVED + 10) #define DRV_QUERYDSOUNDIFACE (DRV_RESERVED + 10)
#define DRV_QUERYDSOUNDDESC (DRV_RESERVED + 11)
#define DRV_QUERYDSOUNDGUID (DRV_RESERVED + 12)
#endif #endif
#define WODM_INIT DRVM_INIT #define WODM_INIT DRVM_INIT