Commit 89b469fe authored by Robert Reif's avatar Robert Reif Committed by Alexandre Julliard

Added support for multiple direct sound devices.

parent 2e24a148
...@@ -84,7 +84,7 @@ static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) { ...@@ -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( ...@@ -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( ...@@ -601,6 +603,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
} }
} }
} }
LeaveCriticalSection(&(This->lock));
return DS_OK; return DS_OK;
} }
......
...@@ -20,8 +20,6 @@ ...@@ -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( ...@@ -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( ...@@ -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 else
{ {
ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC); ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC);
This->ref = 1;
This->state = STATE_STOPPED;
if (lpcGUID) This->ref = 1;
This->guid = *lpcGUID; This->state = STATE_STOPPED;
else
This->guid = GUID_NULL;
InitializeCriticalSection( &(This->lock) ); InitializeCriticalSection( &(This->lock) );
ICOM_VTBL(This) = &dscvt; ICOM_VTBL(This) = &dscvt;
dsound_capture = This; dsound_capture = This;
return IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE)This, lpcGUID ); if (GetDeviceID(lpcGUID, &This->guid) == DS_OK)
} return IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE)This, &This->guid);
} }
WARN("invalid GUID\n");
FIXME( "Unknown GUID %s\n", debugstr_guid(lpcGUID) ); return DSERR_INVALIDPARAM;
*lplpDSC = NULL;
return DSERR_OUTOFMEMORY;
} }
/*************************************************************************** /***************************************************************************
...@@ -163,8 +152,10 @@ DirectSoundCaptureEnumerateA( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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");
......
...@@ -6,7 +6,7 @@ ...@@ -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
...@@ -116,23 +116,8 @@ int ds_hel_queue = DS_HEL_QUEUE; ...@@ -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) ...@@ -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,11 +222,57 @@ void setup_dsound_options(void) ...@@ -231,11 +222,57 @@ 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]
* *
* Enumerate all DirectSound drivers installed in the system * Enumerate all DirectSound drivers installed in the system
...@@ -245,25 +282,56 @@ void setup_dsound_options(void) ...@@ -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;
TRACE("lpDSEnumCallback = %p, lpContext = %p\n", int err;
lpDSEnumCallback, lpContext);
TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
devs = waveOutGetNumDevs(); lpDSEnumCallback, lpContext);
for (wod = 0; wod < devs; ++wod) {
waveOutGetDevCapsA(wod, &wcaps, sizeof(wcaps)); if (lpDSEnumCallback == NULL) {
if (wcaps.dwSupport & WAVECAPS_DIRECTSOUND) { WARN("invalid parameter\n");
TRACE("- Device %u supports DirectSound\n", wod); return DSERR_INVALIDPARAM;
enumerate_devices(lpDSEnumCallback, lpContext); }
return DS_OK;
} devs = waveOutGetNumDevs();
} if (devs > 0) {
return DS_OK; if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) {
GUID temp;
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 = ...@@ -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 * ...@@ -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) {
......
...@@ -38,6 +38,8 @@ extern int ds_hel_queue; ...@@ -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 ...@@ -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;
......
...@@ -983,7 +983,9 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWOR ...@@ -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) {
......
...@@ -184,7 +184,8 @@ HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This) ...@@ -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++) {
......
...@@ -488,6 +488,12 @@ UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1, ...@@ -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;
......
...@@ -4,7 +4,7 @@ SRCDIR = @srcdir@ ...@@ -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
......
...@@ -149,13 +149,16 @@ typedef struct { ...@@ -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) ...@@ -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, ...@@ -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 ...@@ -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) ...@@ -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
......
...@@ -267,6 +267,16 @@ WINE REGISTRY Version 2 ...@@ -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").
......
...@@ -81,6 +81,8 @@ typedef struct { ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment