Added support for multiple direct sound devices.
This commit is contained in:
parent
2e24a148bf
commit
89b469fefe
|
@ -84,7 +84,7 @@ static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) {
|
|||
if (This->dsb)
|
||||
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
|
||||
else if (This->dscb)
|
||||
IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER8)This->dscb);
|
||||
IDirectSoundCaptureBuffer8_Release((LPDIRECTSOUNDCAPTUREBUFFER8)This->dscb);
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
return 0;
|
||||
}
|
||||
|
@ -543,6 +543,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
|
|||
assert(audiobytes1!=audiobytes2);
|
||||
assert(lplpaudioptr1!=lplpaudioptr2);
|
||||
|
||||
EnterCriticalSection(&(This->lock));
|
||||
|
||||
if ((writebytes == This->buflen) &&
|
||||
((This->state == STATE_STARTING) ||
|
||||
(This->state == STATE_PLAYING)))
|
||||
|
@ -601,6 +603,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&(This->lock));
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
*/
|
||||
/*
|
||||
* TODO:
|
||||
* Fix Enumerate for multiple sound devices.
|
||||
* Handle device GUIDs properly.
|
||||
* Implement DirectSoundFullDuplex support.
|
||||
* Implement FX support.
|
||||
*/
|
||||
|
@ -97,6 +95,7 @@ DirectSoundCaptureCreate8(
|
|||
LPDIRECTSOUNDCAPTURE* lplpDSC,
|
||||
LPUNKNOWN pUnkOuter )
|
||||
{
|
||||
IDirectSoundCaptureImpl** ippDSC=(IDirectSoundCaptureImpl**)lplpDSC;
|
||||
TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter);
|
||||
|
||||
if ( pUnkOuter ) {
|
||||
|
@ -110,43 +109,33 @@ DirectSoundCaptureCreate8(
|
|||
}
|
||||
|
||||
/* Default device? */
|
||||
if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) ||
|
||||
IsEqualGUID(lpcGUID, &DSDEVID_DefaultCapture) ||
|
||||
IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoiceCapture) ) {
|
||||
IDirectSoundCaptureImpl** ippDSC=(IDirectSoundCaptureImpl**)lplpDSC;
|
||||
if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
|
||||
lpcGUID = &DSDEVID_DefaultCapture;
|
||||
|
||||
*ippDSC = (IDirectSoundCaptureImpl*)HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureImpl));
|
||||
*ippDSC = (IDirectSoundCaptureImpl*)HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureImpl));
|
||||
|
||||
if (*ippDSC == NULL) {
|
||||
TRACE("couldn't allocate memory\n");
|
||||
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 );
|
||||
}
|
||||
if (*ippDSC == NULL) {
|
||||
TRACE("couldn't allocate memory\n");
|
||||
return DSERR_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC);
|
||||
|
||||
FIXME( "Unknown GUID %s\n", debugstr_guid(lpcGUID) );
|
||||
*lplpDSC = NULL;
|
||||
This->ref = 1;
|
||||
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,
|
||||
LPVOID lpContext)
|
||||
{
|
||||
WAVEINCAPSA wcaps;
|
||||
unsigned devs, wid;
|
||||
DSDRIVERDESC desc;
|
||||
GUID guid;
|
||||
int err;
|
||||
|
||||
TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
|
||||
|
||||
|
@ -174,15 +165,37 @@ DirectSoundCaptureEnumerateA(
|
|||
}
|
||||
|
||||
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) {
|
||||
waveInGetDevCapsA(wid, &wcaps, sizeof(wcaps));
|
||||
if (lpDSEnumCallback) {
|
||||
TRACE("calling lpDSEnumCallback(%s,\"WINE DirectSound\",\"%s\",%p)\n",
|
||||
debugstr_guid(&DSDEVID_DefaultCapture),wcaps.szPname,lpContext);
|
||||
lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, "WINE DirectSound",
|
||||
wcaps.szPname ,lpContext);
|
||||
return DS_OK;
|
||||
}
|
||||
err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
|
||||
if (err == DS_OK) {
|
||||
err = mmErr(waveInMessage((HWAVEIN)wid,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;
|
||||
|
@ -202,9 +215,12 @@ DirectSoundCaptureEnumerateW(
|
|||
LPDSENUMCALLBACKW lpDSEnumCallback,
|
||||
LPVOID lpContext)
|
||||
{
|
||||
WAVEINCAPSW wcaps;
|
||||
unsigned devs, wid;
|
||||
WCHAR desc[MAXPNAMELEN];
|
||||
DSDRIVERDESC desc;
|
||||
GUID guid;
|
||||
int err;
|
||||
WCHAR wDesc[MAXPNAMELEN];
|
||||
WCHAR wName[MAXPNAMELEN];
|
||||
|
||||
TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
|
||||
|
||||
|
@ -214,14 +230,45 @@ DirectSoundCaptureEnumerateW(
|
|||
}
|
||||
|
||||
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) {
|
||||
waveInGetDevCapsW(wid, &wcaps, sizeof(wcaps));
|
||||
if (lpDSEnumCallback) {
|
||||
MultiByteToWideChar( CP_ACP, 0, "WINE Sound Capture Driver", -1,
|
||||
desc, sizeof(desc)/sizeof(WCHAR) );
|
||||
lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, desc, wcaps.szPname ,lpContext);
|
||||
return DS_OK;
|
||||
}
|
||||
err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
|
||||
if (err == DS_OK) {
|
||||
err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
|
||||
if (err == DS_OK) {
|
||||
TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
|
||||
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;
|
||||
|
@ -402,7 +449,7 @@ IDirectSoundCaptureImpl_Initialize(
|
|||
LPDIRECTSOUNDCAPTURE iface,
|
||||
LPCGUID lpcGUID )
|
||||
{
|
||||
HRESULT err = DS_OK;
|
||||
HRESULT err = DSERR_INVALIDPARAM;
|
||||
unsigned wid, widn;
|
||||
ICOM_THIS(IDirectSoundCaptureImpl,iface);
|
||||
TRACE("(%p)\n", This);
|
||||
|
@ -427,8 +474,24 @@ IDirectSoundCaptureImpl_Initialize(
|
|||
/* Get dsound configuration */
|
||||
setup_dsound_options();
|
||||
|
||||
/* FIXME: should enumerate WINMM audio devices and find the one we want */
|
||||
wid = 0;
|
||||
/* enumerate WINMM audio devices and find the one we want */
|
||||
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));
|
||||
if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
|
||||
|
@ -443,9 +506,6 @@ IDirectSoundCaptureImpl_Initialize(
|
|||
|
||||
/* Get driver description */
|
||||
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");
|
||||
err = IDsCaptureDriver_GetDriverDesc(This->driver, &(This->drvdesc));
|
||||
if (err != DS_OK) {
|
||||
|
@ -484,11 +544,9 @@ IDirectSoundCaptureImpl_Initialize(
|
|||
strncpy(This->drvdesc.szDrvName, wic.szPname,
|
||||
sizeof(This->drvdesc.szDrvName));
|
||||
|
||||
This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
|
||||
This->drvcaps.dwFormats = wic.dwFormats;
|
||||
This->drvcaps.dwChannels = wic.wChannels;
|
||||
|
||||
if (ds_emuldriver)
|
||||
This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -656,7 +714,7 @@ IDirectSoundCaptureBufferImpl_QueryInterface(
|
|||
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;
|
||||
}
|
||||
|
@ -1226,7 +1284,7 @@ DirectSoundFullDuplexCreate8(
|
|||
}
|
||||
|
||||
*ippDSFD = (IDirectSoundFullDuplexImpl*)HeapAlloc(GetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
|
||||
HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
|
||||
|
||||
if (*ippDSFD == NULL) {
|
||||
TRACE("couldn't allocate memory\n");
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
6 stdcall DirectSoundCaptureCreate(ptr ptr ptr) DirectSoundCaptureCreate8
|
||||
7 stdcall DirectSoundCaptureEnumerateA(ptr ptr) DirectSoundCaptureEnumerateA
|
||||
8 stdcall DirectSoundCaptureEnumerateW(ptr ptr) DirectSoundCaptureEnumerateW
|
||||
9 stub GetDeviceID
|
||||
9 stdcall GetDeviceID(ptr ptr) GetDeviceID
|
||||
10 stub DirectSoundFullDuplexCreate
|
||||
11 stdcall DirectSoundCreate8(ptr ptr ptr) DirectSoundCreate8
|
||||
12 stdcall DirectSoundCaptureCreate8(ptr ptr ptr) DirectSoundCaptureCreate8
|
||||
|
|
|
@ -116,23 +116,8 @@ int ds_hel_queue = DS_HEL_QUEUE;
|
|||
int ds_snd_queue_max = DS_SND_QUEUE_MAX;
|
||||
int ds_snd_queue_min = DS_SND_QUEUE_MIN;
|
||||
int ds_hw_accel = DS_HW_ACCEL_FULL;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
int ds_default_playback = 0;
|
||||
int ds_default_capture = 0;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
if (!get_config_key( hkey, appkey, "DefaultPlayback", buffer, MAX_PATH ))
|
||||
ds_default_playback = atoi(buffer);
|
||||
|
||||
if (!get_config_key( hkey, appkey, "DefaultCapture", buffer, MAX_PATH ))
|
||||
ds_default_capture = atoi(buffer);
|
||||
|
||||
if (appkey) RegCloseKey( appkey );
|
||||
RegCloseKey( hkey );
|
||||
|
||||
|
@ -231,10 +222,56 @@ void setup_dsound_options(void)
|
|||
ds_hw_accel==DS_HW_ACCEL_BASIC ? "Basic" :
|
||||
ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" :
|
||||
"Unknown");
|
||||
if (ds_default_playback != 0)
|
||||
WARN("ds_default_playback = %d (default=0)\n",ds_default_playback);
|
||||
if (ds_default_capture != 0)
|
||||
WARN("ds_default_capture = %d (default=0)\n",ds_default_playback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* 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]
|
||||
*
|
||||
|
@ -245,25 +282,56 @@ void setup_dsound_options(void)
|
|||
* Failure: DSERR_INVALIDPARAM
|
||||
*/
|
||||
HRESULT WINAPI DirectSoundEnumerateA(
|
||||
LPDSENUMCALLBACKA lpDSEnumCallback,
|
||||
LPVOID lpContext)
|
||||
LPDSENUMCALLBACKA lpDSEnumCallback,
|
||||
LPVOID lpContext)
|
||||
{
|
||||
WAVEOUTCAPSA wcaps;
|
||||
unsigned devs, wod;
|
||||
unsigned devs, wod;
|
||||
DSDRIVERDESC desc;
|
||||
GUID guid;
|
||||
int err;
|
||||
|
||||
TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
|
||||
lpDSEnumCallback, lpContext);
|
||||
TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
|
||||
lpDSEnumCallback, lpContext);
|
||||
|
||||
devs = waveOutGetNumDevs();
|
||||
for (wod = 0; wod < devs; ++wod) {
|
||||
waveOutGetDevCapsA(wod, &wcaps, sizeof(wcaps));
|
||||
if (wcaps.dwSupport & WAVECAPS_DIRECTSOUND) {
|
||||
TRACE("- Device %u supports DirectSound\n", wod);
|
||||
enumerate_devices(lpDSEnumCallback, lpContext);
|
||||
return DS_OK;
|
||||
}
|
||||
}
|
||||
return DS_OK;
|
||||
if (lpDSEnumCallback == NULL) {
|
||||
WARN("invalid parameter\n");
|
||||
return DSERR_INVALIDPARAM;
|
||||
}
|
||||
|
||||
devs = waveOutGetNumDevs();
|
||||
if (devs > 0) {
|
||||
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 =
|
|||
/*******************************************************************************
|
||||
* 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;
|
||||
PIDSDRIVER drv = NULL;
|
||||
unsigned wod, wodn;
|
||||
HRESULT err = DS_OK;
|
||||
|
||||
if (lpGUID)
|
||||
TRACE("(%p,%p,%p)\n",lpGUID,ippDS,pUnkOuter);
|
||||
else
|
||||
TRACE("DirectSoundCreate (%p)\n", ippDS);
|
||||
HRESULT err = DSERR_INVALIDPARAM;
|
||||
GUID devGuid;
|
||||
TRACE("(%p,%p,%p)\n",lpcGUID,ippDS,pUnkOuter);
|
||||
|
||||
if (ippDS == NULL)
|
||||
return DSERR_INVALIDPARAM;
|
||||
|
||||
if (dsound) {
|
||||
IDirectSound_AddRef((LPDIRECTSOUND)dsound);
|
||||
*ippDS = dsound;
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
/* Get dsound configuration */
|
||||
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 */
|
||||
wodn = waveOutGetNumDevs();
|
||||
if (!wodn) return DSERR_NODRIVER;
|
||||
|
||||
/* FIXME: How do we find the GUID of an audio device? */
|
||||
wod = 0; /* start at the first audio device */
|
||||
for (wod=0; wod<wodn; wod++) {
|
||||
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 */
|
||||
waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
|
||||
|
@ -648,6 +742,7 @@ HRESULT WINAPI DirectSoundCreate8(REFGUID lpGUID,LPDIRECTSOUND8 *ppDS,IUnknown *
|
|||
(*ippDS)->listener = NULL;
|
||||
|
||||
(*ippDS)->prebuf = ds_snd_queue_max;
|
||||
(*ippDS)->guid = devGuid;
|
||||
|
||||
/* Get driver description */
|
||||
if (drv) {
|
||||
|
|
|
@ -38,6 +38,8 @@ extern int ds_hel_queue;
|
|||
extern int ds_snd_queue_max;
|
||||
extern int ds_snd_queue_min;
|
||||
extern int ds_hw_accel;
|
||||
extern int ds_default_playback;
|
||||
extern int ds_default_capture;
|
||||
|
||||
/*****************************************************************************
|
||||
* Predeclare the interface implementation structures
|
||||
|
@ -62,6 +64,7 @@ struct IDirectSoundImpl
|
|||
ICOM_VFIELD(IDirectSound8);
|
||||
DWORD ref;
|
||||
/* IDirectSoundImpl fields */
|
||||
GUID guid;
|
||||
PIDSDRIVER driver;
|
||||
DSDRIVERDESC drvdesc;
|
||||
DSDRIVERCAPS drvcaps;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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) {
|
||||
DWORD inq, mixq, fraglen, buflen, pwplay, playpos, mixpos;
|
||||
if (This->pwqueue == (DWORD)-1) {
|
||||
|
|
|
@ -184,7 +184,8 @@ HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This)
|
|||
{
|
||||
DSOUND_PrimaryClose(This);
|
||||
if (This->hwbuf) {
|
||||
IDsDriverBuffer_Release(This->hwbuf);
|
||||
if (IDsDriverBuffer_Release(This->hwbuf) == 0)
|
||||
This->hwbuf = 0;
|
||||
} else {
|
||||
unsigned c;
|
||||
for (c=0; c<DS_HEL_FRAGS; c++) {
|
||||
|
|
|
@ -488,6 +488,12 @@ UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, DWORD dwParam1,
|
|||
case DRV_QUERYDSOUNDIFACE: /* Wine-specific: Retrieve DirectSound interface */
|
||||
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:
|
||||
WARN("Unknown call %04x\n", uMsg);
|
||||
return MMSYSERR_INVALPARAM;
|
||||
|
|
|
@ -4,7 +4,7 @@ SRCDIR = @srcdir@
|
|||
VPATH = @srcdir@
|
||||
MODULE = winealsa.drv
|
||||
IMPORTS = winmm user32 kernel32 ntdll
|
||||
EXTRALIBS = @ALSALIBS@
|
||||
EXTRALIBS = $(LIBUUID) @ALSALIBS@
|
||||
|
||||
LDDLLFLAGS = @LDDLLFLAGS@
|
||||
SYMBOLFILE = $(MODULE).tmp.o
|
||||
|
|
|
@ -149,13 +149,16 @@ typedef struct {
|
|||
ALSA_MSG_RING msgRing;
|
||||
|
||||
/* DirectSound stuff */
|
||||
|
||||
DSDRIVERDESC ds_desc;
|
||||
GUID ds_guid;
|
||||
} WINE_WAVEOUT;
|
||||
|
||||
static WINE_WAVEOUT WOutDev [MAX_WAVEOUTDRV];
|
||||
static DWORD ALSA_WodNumDevs;
|
||||
|
||||
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 */
|
||||
#if 0
|
||||
|
@ -412,6 +415,9 @@ LONG ALSA_WaveInit(void)
|
|||
wwo->caps.vDriverVersion = 0x0100;
|
||||
wwo->caps.dwFormats = 0x00000000;
|
||||
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))
|
||||
{
|
||||
|
@ -1572,7 +1578,10 @@ DWORD WINAPI ALSA_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
|
|||
case WODM_SETVOLUME: return wodSetVolume (wDevID, dwParam1);
|
||||
case WODM_RESTART: return wodRestart (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:
|
||||
FIXME("unknown message %d!\n", wMsg);
|
||||
}
|
||||
|
@ -1947,10 +1956,9 @@ static HRESULT WINAPI IDsDriverImpl_GetDriverDesc(PIDSDRIVER iface, PDSDRIVERDES
|
|||
{
|
||||
ICOM_THIS(IDsDriverImpl,iface);
|
||||
TRACE("(%p,%p)\n",iface,pDesc);
|
||||
memcpy(pDesc, &(WOutDev[This->wDevID].ds_desc), sizeof(DSDRIVERDESC));
|
||||
pDesc->dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT |
|
||||
DSDDESC_USESYSTEMMEMORY;
|
||||
strcpy(pDesc->szDesc, "WineALSA DirectSound Driver");
|
||||
strcpy(pDesc->szDrvName, "winealsa.drv");
|
||||
pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode;
|
||||
pDesc->wVxdId = 0;
|
||||
pDesc->wReserved = 0;
|
||||
|
@ -2094,6 +2102,22 @@ static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
|
|||
(*idrv)->primary = NULL;
|
||||
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
|
||||
|
||||
#ifndef HAVE_ALSA
|
||||
|
|
|
@ -73,7 +73,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wave);
|
|||
|
||||
#ifdef HAVE_OSS
|
||||
|
||||
#define MAX_WAVEDRV (3)
|
||||
#define MAX_WAVEDRV (6)
|
||||
|
||||
/* state diagram for waveOut writing:
|
||||
*
|
||||
|
@ -145,8 +145,8 @@ typedef struct {
|
|||
} OSS_MSG_RING;
|
||||
|
||||
typedef struct tagOSS_DEVICE {
|
||||
const char* dev_name;
|
||||
const char* mixer_name;
|
||||
char dev_name[32];
|
||||
char mixer_name[32];
|
||||
unsigned open_count;
|
||||
WAVEOUTCAPSA out_caps;
|
||||
WAVEINCAPSA in_caps;
|
||||
|
@ -162,6 +162,11 @@ typedef struct tagOSS_DEVICE {
|
|||
BOOL bTriggerSupport;
|
||||
BOOL bOutputEnabled;
|
||||
BOOL bInputEnabled;
|
||||
DSDRIVERDESC ds_desc;
|
||||
DSDRIVERCAPS ds_caps;
|
||||
DSCDRIVERCAPS dsc_caps;
|
||||
GUID ds_guid;
|
||||
GUID dsc_guid;
|
||||
} OSS_DEVICE;
|
||||
|
||||
static OSS_DEVICE OSS_Devices[MAX_WAVEDRV];
|
||||
|
@ -226,6 +231,10 @@ static unsigned numInDev;
|
|||
|
||||
static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* 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 */
|
||||
static const char *wodPlayerCmdString[] = {
|
||||
|
@ -258,6 +267,7 @@ static int getEnables(OSS_DEVICE *ossdev)
|
|||
static DWORD OSS_RawOpenDevice(OSS_DEVICE* ossdev, int strict_format)
|
||||
{
|
||||
int fd, val, rc;
|
||||
TRACE("(%p,%d)\n",ossdev,strict_format);
|
||||
|
||||
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 */
|
||||
/* turn full duplex on if it has been requested */
|
||||
if (ossdev->open_access == O_RDWR && ossdev->full_duplex)
|
||||
ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
|
||||
if (ossdev->open_access == O_RDWR && ossdev->full_duplex) {
|
||||
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)
|
||||
{
|
||||
ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &ossdev->audio_fragment);
|
||||
if (ossdev->audio_fragment) {
|
||||
rc = 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 */
|
||||
|
@ -306,8 +324,22 @@ static DWORD OSS_RawOpenDevice(OSS_DEVICE* ossdev, int strict_format)
|
|||
}
|
||||
}
|
||||
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;
|
||||
|
||||
|
@ -328,6 +360,7 @@ static DWORD OSS_OpenDevice(OSS_DEVICE* ossdev, unsigned req_access,
|
|||
int sample_rate, int stereo, int fmt)
|
||||
{
|
||||
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))
|
||||
req_access = O_RDWR;
|
||||
|
@ -354,6 +387,7 @@ static DWORD OSS_OpenDevice(OSS_DEVICE* ossdev, unsigned req_access,
|
|||
WARN("Mismatch in access...\n");
|
||||
return WAVERR_BADFORMAT;
|
||||
}
|
||||
|
||||
/* FIXME: if really needed, we could do, in this case, on the fly
|
||||
* 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)
|
||||
{
|
||||
TRACE("(%p)\n",ossdev);
|
||||
if (ossdev->open_count>0) {
|
||||
ossdev->open_count--;
|
||||
} else {
|
||||
|
@ -456,10 +491,33 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
|
|||
{
|
||||
int rc,arg;
|
||||
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;
|
||||
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
|
||||
* registry for MM drivers. The names have to match in order for the
|
||||
* program to work (e.g. MS win9x mplayer.exe)
|
||||
|
@ -471,8 +529,6 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
|
|||
#else
|
||||
ossdev->out_caps.wMid = 0x00FF; /* Manufac 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
|
||||
ossdev->out_caps.vDriverVersion = 0x0100;
|
||||
ossdev->out_caps.wChannels = 1;
|
||||
|
@ -480,6 +536,10 @@ static BOOL OSS_WaveOutInit(OSS_DEVICE* ossdev)
|
|||
ossdev->out_caps.wReserved1 = 0;
|
||||
ossdev->out_caps.dwSupport = WAVECAPS_VOLUME;
|
||||
|
||||
/* direct sound caps */
|
||||
ossdev->ds_caps.dwFlags = 0;
|
||||
ossdev->ds_caps.dwPrimaryBuffers = 1;
|
||||
|
||||
if (WINE_TRACE_ON(wave)) {
|
||||
/* Note that this only reports the formats supported by the hardware.
|
||||
* 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];
|
||||
rc=ioctl(ossdev->fd, SNDCTL_DSP_SAMPLESIZE, &arg);
|
||||
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]);
|
||||
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++) {
|
||||
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);
|
||||
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.dwSupport|=WAVECAPS_LRVOLUME;
|
||||
ossdev->ds_caps.dwFlags |= DSCAPS_PRIMARYSTEREO;
|
||||
}
|
||||
|
||||
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 */
|
||||
if ((arg & DSP_CAP_TRIGGER) && (arg & DSP_CAP_MMAP) &&
|
||||
!(arg & DSP_CAP_BATCH))
|
||||
!(arg & DSP_CAP_BATCH)) {
|
||||
ossdev->out_caps.dwSupport |= WAVECAPS_DIRECTSOUND;
|
||||
} else {
|
||||
ossdev->ds_caps.dwFlags |= DSCAPS_EMULDRIVER;
|
||||
}
|
||||
}
|
||||
OSS_CloseDevice(ossdev);
|
||||
TRACE("out dwFormats = %08lX, dwSupport = %08lX\n",
|
||||
|
@ -554,10 +624,31 @@ static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
|
|||
{
|
||||
int rc,arg;
|
||||
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;
|
||||
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 */
|
||||
#ifdef EMULATE_SB16
|
||||
ossdev->in_caps.wMid = 0x0002;
|
||||
|
@ -566,13 +657,18 @@ static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
|
|||
#else
|
||||
ossdev->in_caps.wMid = 0x00FF; /* Manufac ID */
|
||||
ossdev->in_caps.wPid = 0x0001; /* Product ID */
|
||||
strcpy(ossdev->in_caps.szPname, "OpenSoundSystem WAVIN Driver");
|
||||
#endif
|
||||
ossdev->in_caps.dwFormats = 0x00000000;
|
||||
ossdev->in_caps.wChannels = 1;
|
||||
ossdev->in_caps.wReserved1 = 0;
|
||||
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)) {
|
||||
/* Note that this only reports the formats supported by the hardware.
|
||||
* 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) {
|
||||
ossdev->in_caps.wChannels=2;
|
||||
ossdev->dsc_caps.dwChannels=2;
|
||||
}
|
||||
|
||||
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);
|
||||
if (rc==0 && NEAR_MATCH(arg,win_std_rates[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)
|
||||
ossdev->bTriggerSupport = TRUE;
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
if ((arg & DSP_CAP_REALTIME) && !(arg & DSP_CAP_BATCH))
|
||||
ossdev->in_caps_support |= WAVECAPS_SAMPLEACCURATE;
|
||||
}
|
||||
|
@ -637,6 +739,7 @@ static BOOL OSS_WaveInInit(OSS_DEVICE* ossdev)
|
|||
static void OSS_WaveFullDuplexInit(OSS_DEVICE* ossdev)
|
||||
{
|
||||
int caps;
|
||||
TRACE("(%p)\n",ossdev);
|
||||
|
||||
if (OSS_OpenDevice(ossdev, O_RDWR, NULL, 0,-1,-1,-1) != 0) return;
|
||||
if (ioctl(ossdev->fd, SNDCTL_DSP_GETCAPS, &caps) == 0)
|
||||
|
@ -646,6 +749,11 @@ static void OSS_WaveFullDuplexInit(OSS_DEVICE* 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
|
||||
*
|
||||
|
@ -654,6 +762,7 @@ static void OSS_WaveFullDuplexInit(OSS_DEVICE* ossdev)
|
|||
LONG OSS_WaveInit(void)
|
||||
{
|
||||
int i;
|
||||
TRACE("()\n");
|
||||
|
||||
/* FIXME: only one device is supported */
|
||||
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...
|
||||
* - or even store the name of all drivers in our configuration
|
||||
*/
|
||||
OSS_Devices[0].dev_name = "/dev/dsp";
|
||||
OSS_Devices[0].mixer_name = "/dev/mixer";
|
||||
OSS_Devices[1].dev_name = "/dev/dsp1";
|
||||
OSS_Devices[1].mixer_name = "/dev/mixer1";
|
||||
OSS_Devices[2].dev_name = "/dev/dsp2";
|
||||
OSS_Devices[2].mixer_name = "/dev/mixer2";
|
||||
for (i = 0; i < MAX_WAVEDRV; ++i)
|
||||
{
|
||||
if (i == 0) {
|
||||
sprintf((char *)OSS_Devices[i].dev_name, "/dev/dsp");
|
||||
sprintf((char *)OSS_Devices[i].mixer_name, "/dev/mixer");
|
||||
} 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 */
|
||||
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 (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;
|
||||
}
|
||||
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 */
|
||||
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);
|
||||
wwo->state = WINE_WS_CLOSED;
|
||||
return MMSYSERR_NOTENABLED;
|
||||
|
@ -1731,7 +1847,7 @@ static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
|
|||
return MMSYSERR_NOTENABLED;
|
||||
}
|
||||
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;
|
||||
}
|
||||
close(mixer);
|
||||
|
@ -1764,7 +1880,7 @@ static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
|
|||
return MMSYSERR_NOTENABLED;
|
||||
}
|
||||
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;
|
||||
} else {
|
||||
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_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:
|
||||
FIXME("unknown message %d!\n", wMsg);
|
||||
}
|
||||
|
@ -1845,6 +1963,7 @@ struct IDsDriverBufferImpl
|
|||
static HRESULT DSDB_MapPrimary(IDsDriverBufferImpl *dsdb)
|
||||
{
|
||||
WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]);
|
||||
TRACE("(%p)\n",dsdb);
|
||||
if (!wwo->mapping) {
|
||||
wwo->mapping = mmap(NULL, wwo->maplen, PROT_WRITE, MAP_SHARED,
|
||||
wwo->ossdev->fd, 0);
|
||||
|
@ -1887,9 +2006,10 @@ static HRESULT DSDB_MapPrimary(IDsDriverBufferImpl *dsdb)
|
|||
static HRESULT DSDB_UnmapPrimary(IDsDriverBufferImpl *dsdb)
|
||||
{
|
||||
WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]);
|
||||
TRACE("(%p)\n",dsdb);
|
||||
if (wwo->mapping) {
|
||||
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;
|
||||
}
|
||||
wwo->mapping = NULL;
|
||||
|
@ -1908,19 +2028,25 @@ static HRESULT WINAPI IDsDriverBufferImpl_QueryInterface(PIDSDRIVERBUFFER iface,
|
|||
static ULONG WINAPI IDsDriverBufferImpl_AddRef(PIDSDRIVERBUFFER iface)
|
||||
{
|
||||
ICOM_THIS(IDsDriverBufferImpl,iface);
|
||||
TRACE("(%p)\n",This);
|
||||
This->ref++;
|
||||
TRACE("ref=%ld\n",This->ref);
|
||||
return This->ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI IDsDriverBufferImpl_Release(PIDSDRIVERBUFFER iface)
|
||||
{
|
||||
ICOM_THIS(IDsDriverBufferImpl,iface);
|
||||
if (--This->ref)
|
||||
TRACE("(%p)\n",This);
|
||||
if (--This->ref) {
|
||||
TRACE("ref=%ld\n",This->ref);
|
||||
return This->ref;
|
||||
}
|
||||
if (This == This->drv->primary)
|
||||
This->drv->primary = NULL;
|
||||
DSDB_UnmapPrimary(This);
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
TRACE("ref=0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1995,7 +2121,7 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,
|
|||
return DSERR_UNINITIALIZED;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
enable = getEnables(WOutDev[This->drv->wDevID].ossdev);
|
||||
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;
|
||||
return DSERR_GENERIC;
|
||||
}
|
||||
|
@ -2037,13 +2163,13 @@ static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface)
|
|||
WOutDev[This->drv->wDevID].ossdev->bOutputEnabled = FALSE;
|
||||
enable = getEnables(WOutDev[This->drv->wDevID].ossdev);
|
||||
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;
|
||||
}
|
||||
#if 0
|
||||
/* the play position must be reset to the beginning of the buffer */
|
||||
if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_RESET, 0) < 0) {
|
||||
ERR("ioctl failed (%d)\n", errno);
|
||||
if (ioctl(WOutDev[This->drv->wDevID].ossdev->fd, SNDCTL_DSP_RESET, 0) < 0) {
|
||||
ERR("ioctl(%s, SNDCTL_DSP_RESET) failed (%s)\n", WOutDev[This->drv->wDevID].ossdev->dev_name, strerror(errno));
|
||||
return DSERR_GENERIC;
|
||||
}
|
||||
#endif
|
||||
|
@ -2081,16 +2207,22 @@ static HRESULT WINAPI IDsDriverImpl_QueryInterface(PIDSDRIVER iface, REFIID riid
|
|||
static ULONG WINAPI IDsDriverImpl_AddRef(PIDSDRIVER iface)
|
||||
{
|
||||
ICOM_THIS(IDsDriverImpl,iface);
|
||||
TRACE("(%p)\n",This);
|
||||
This->ref++;
|
||||
TRACE("ref=%ld\n",This->ref);
|
||||
return This->ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI IDsDriverImpl_Release(PIDSDRIVER iface)
|
||||
{
|
||||
ICOM_THIS(IDsDriverImpl,iface);
|
||||
if (--This->ref)
|
||||
TRACE("(%p)\n",This);
|
||||
if (--This->ref) {
|
||||
TRACE("ref=%ld\n",This->ref);
|
||||
return This->ref;
|
||||
}
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
TRACE("ref=0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2098,10 +2230,12 @@ static HRESULT WINAPI IDsDriverImpl_GetDriverDesc(PIDSDRIVER iface, PDSDRIVERDES
|
|||
{
|
||||
ICOM_THIS(IDsDriverImpl,iface);
|
||||
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;
|
||||
strcpy(pDesc->szDesc,"WineOSS DirectSound Driver");
|
||||
strcpy(pDesc->szDrvName,"wineoss.drv");
|
||||
pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode;
|
||||
pDesc->wVxdId = 0;
|
||||
pDesc->wReserved = 0;
|
||||
|
@ -2126,7 +2260,7 @@ static HRESULT WINAPI IDsDriverImpl_Open(PIDSDRIVER iface)
|
|||
WOutDev[This->wDevID].ossdev->bOutputEnabled = FALSE;
|
||||
enable = getEnables(WOutDev[This->wDevID].ossdev);
|
||||
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 DS_OK;
|
||||
|
@ -2145,15 +2279,9 @@ static HRESULT WINAPI IDsDriverImpl_Close(PIDSDRIVER iface)
|
|||
|
||||
static HRESULT WINAPI IDsDriverImpl_GetCaps(PIDSDRIVER iface, PDSDRIVERCAPS pCaps)
|
||||
{
|
||||
/* ICOM_THIS(IDsDriverImpl,iface); */
|
||||
ICOM_THIS(IDsDriverImpl,iface);
|
||||
TRACE("(%p,%p)\n",iface,pCaps);
|
||||
memset(pCaps, 0, sizeof(*pCaps));
|
||||
/* 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) */
|
||||
memcpy(pCaps, &(WOutDev[This->wDevID].ossdev->ds_caps), sizeof(DSDRIVERCAPS));
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
|
@ -2169,8 +2297,8 @@ static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface,
|
|||
HRESULT err;
|
||||
audio_buf_info info;
|
||||
int enable = 0;
|
||||
|
||||
TRACE("(%p,%p,%lx,%lx)\n",iface,pwfx,dwFlags,dwCardAddress);
|
||||
|
||||
/* we only support primary buffers */
|
||||
if (!(dwFlags & DSBCAPS_PRIMARYBUFFER))
|
||||
return DSERR_UNSUPPORTED;
|
||||
|
@ -2188,7 +2316,7 @@ static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface,
|
|||
|
||||
/* check how big the DMA buffer is now */
|
||||
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);
|
||||
*ippdsdb = NULL;
|
||||
return DSERR_GENERIC;
|
||||
|
@ -2211,7 +2339,7 @@ static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface,
|
|||
WOutDev[This->wDevID].ossdev->bOutputEnabled = FALSE;
|
||||
enable = getEnables(WOutDev[This->wDevID].ossdev);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -2246,6 +2374,7 @@ static ICOM_VTABLE(IDsDriver) dsdvt =
|
|||
static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* 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() */
|
||||
if (!(WOutDev[wDevID].ossdev->out_caps.dwSupport & WAVECAPS_DIRECTSOUND)) {
|
||||
|
@ -2266,6 +2395,20 @@ static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv)
|
|||
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 *
|
||||
*======================================================================*/
|
||||
|
@ -2343,7 +2486,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
|
|||
wwi->ossdev->bInputEnabled = FALSE;
|
||||
enable = getEnables(wwi->ossdev);
|
||||
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
|
||||
* (or GETISPACE will have 0 frags all the time)
|
||||
|
@ -2499,7 +2642,7 @@ static DWORD CALLBACK widRecorder(LPVOID pmt)
|
|||
enable = getEnables(wwi->ossdev);
|
||||
if (ioctl(wwi->ossdev->fd, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {
|
||||
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
|
||||
|
@ -2650,7 +2793,7 @@ static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
|
|||
|
||||
ioctl(wwi->ossdev->fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
|
||||
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);
|
||||
wwi->state = WINE_WS_CLOSED;
|
||||
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_STOP: return widStop (wDevID);
|
||||
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:
|
||||
FIXME("unknown message %u!\n", wMsg);
|
||||
}
|
||||
|
@ -3047,7 +3192,7 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_GetPosition(PIDSCDRIVERBUFFER i
|
|||
return DSERR_UNINITIALIZED;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
enable = getEnables(WInDev[This->drv->wDevID].ossdev);
|
||||
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;
|
||||
return DSERR_GENERIC;
|
||||
}
|
||||
|
@ -3096,7 +3241,7 @@ static HRESULT WINAPI IDsCaptureDriverBufferImpl_Stop(PIDSCDRIVERBUFFER iface)
|
|||
WInDev[This->drv->wDevID].ossdev->bInputEnabled = FALSE;
|
||||
enable = getEnables(WInDev[This->drv->wDevID].ossdev);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -3139,16 +3284,22 @@ static HRESULT WINAPI IDsCaptureDriverImpl_QueryInterface(PIDSCDRIVER iface, REF
|
|||
static ULONG WINAPI IDsCaptureDriverImpl_AddRef(PIDSCDRIVER iface)
|
||||
{
|
||||
ICOM_THIS(IDsCaptureDriverImpl,iface);
|
||||
TRACE("(%p)\n",This);
|
||||
This->ref++;
|
||||
TRACE("ref=%ld\n",This->ref);
|
||||
return This->ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI IDsCaptureDriverImpl_Release(PIDSCDRIVER iface)
|
||||
{
|
||||
ICOM_THIS(IDsCaptureDriverImpl,iface);
|
||||
if (--This->ref)
|
||||
TRACE("(%p)\n",This);
|
||||
if (--This->ref) {
|
||||
TRACE("ref=%ld\n",This->ref);
|
||||
return This->ref;
|
||||
}
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
TRACE("ref=0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3162,11 +3313,12 @@ static HRESULT WINAPI IDsCaptureDriverImpl_GetDriverDesc(PIDSCDRIVER iface, PDSD
|
|||
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_DONTNEEDSECONDARYLOCK;
|
||||
strcpy(pDesc->szDesc,"WineOSS DirectSound Driver");
|
||||
strcpy(pDesc->szDrvName,"wineoss.drv");
|
||||
pDesc->dnDevNode = WInDev[This->wDevID].waveDesc.dnDevNode;
|
||||
pDesc->wVxdId = 0;
|
||||
pDesc->wReserved = 0;
|
||||
|
@ -3203,16 +3355,7 @@ static HRESULT WINAPI IDsCaptureDriverImpl_GetCaps(PIDSCDRIVER iface, PDSCDRIVER
|
|||
{
|
||||
ICOM_THIS(IDsCaptureDriverImpl,iface);
|
||||
TRACE("(%p,%p)\n",This,pCaps);
|
||||
|
||||
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;
|
||||
|
||||
memcpy(pCaps, &(WInDev[This->wDevID].ossdev->dsc_caps), sizeof(DSCDRIVERCAPS));
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
|
@ -3263,7 +3406,7 @@ static HRESULT WINAPI IDsCaptureDriverImpl_CreateCaptureBuffer(PIDSCDRIVER iface
|
|||
|
||||
/* check how big the DMA buffer is now */
|
||||
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);
|
||||
*ippdscdb = NULL;
|
||||
return DSERR_GENERIC;
|
||||
|
@ -3286,7 +3429,7 @@ static HRESULT WINAPI IDsCaptureDriverImpl_CreateCaptureBuffer(PIDSCDRIVER iface
|
|||
WInDev[This->wDevID].ossdev->bInputEnabled = FALSE;
|
||||
enable = getEnables(WInDev[This->wDevID].ossdev);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -3332,6 +3475,21 @@ static DWORD widDsCreate(UINT wDevID, PIDSCDRIVER* drv)
|
|||
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 */
|
||||
|
||||
/**************************************************************************
|
||||
|
|
|
@ -267,6 +267,16 @@ WINE REGISTRY Version 2
|
|||
;"SndQueueMax" = "28"
|
||||
;; Min number of fragments to prebuffer
|
||||
;"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]
|
||||
;; Use the DNS (Unix) host name always as NetBIOS "ComputerName" (boolean, default "Y").
|
||||
|
|
|
@ -81,6 +81,8 @@ typedef struct {
|
|||
#define DRV_QUERYMAPPABLE (DRV_RESERVED + 5)
|
||||
#ifdef __WINESRC__
|
||||
#define DRV_QUERYDSOUNDIFACE (DRV_RESERVED + 10)
|
||||
#define DRV_QUERYDSOUNDDESC (DRV_RESERVED + 11)
|
||||
#define DRV_QUERYDSOUNDGUID (DRV_RESERVED + 12)
|
||||
#endif
|
||||
|
||||
#define WODM_INIT DRVM_INIT
|
||||
|
|
Loading…
Reference in New Issue