| /* DirectSound | |
| * | |
| * Copyright 1998 Marcus Meissner | |
| * Copyright 1998 Rob Riggs | |
| * Copyright 2000-2001 TransGaming Technologies, Inc. | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| /* | |
| * Most thread locking is complete. There may be a few race | |
| * conditions still lurking. | |
| * | |
| * Tested with a Soundblaster clone, a Gravis UltraSound Classic, | |
| * and a Turtle Beach Tropez+. | |
| * | |
| * TODO: | |
| * Implement SetCooperativeLevel properly (need to address focus issues) | |
| * Implement DirectSound3DBuffers (stubs in place) | |
| * Use hardware 3D support if available | |
| * Add critical section locking inside Release and AddRef methods | |
| * Handle static buffers - put those in hardware, non-static not in hardware | |
| * Hardware DuplicateSoundBuffer | |
| * Proper volume calculation, and setting volume in HEL primary buffer | |
| * Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN | |
| */ | |
| #include "config.h" | |
| #include <assert.h> | |
| #include <stdio.h> | |
| #include <sys/types.h> | |
| #include <sys/fcntl.h> | |
| #ifdef HAVE_UNISTD_H | |
| # include <unistd.h> | |
| #endif | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <math.h> /* Insomnia - pow() function */ | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "wingdi.h" | |
| #include "winuser.h" | |
| #include "winerror.h" | |
| #include "mmsystem.h" | |
| #include "winternl.h" | |
| #include "mmddk.h" | |
| #include "wine/windef16.h" | |
| #include "wine/debug.h" | |
| #include "dsound.h" | |
| #include "dsdriver.h" | |
| #include "dsound_private.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(dsound); | |
| /******************************************************************************* | |
| * IDirectSound3DBuffer | |
| */ | |
| /* IUnknown methods */ | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface( | |
| LPDIRECTSOUND3DBUFFER iface, REFIID riid, LPVOID *ppobj) | |
| { | |
| ICOM_THIS(IDirectSound3DBufferImpl,iface); | |
| TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); | |
| return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj); | |
| } | |
| static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface) | |
| { | |
| ICOM_THIS(IDirectSound3DBufferImpl,iface); | |
| ULONG ulReturn; | |
| TRACE("(%p) ref was %ld\n", This, This->ref); | |
| ulReturn = InterlockedIncrement(&This->ref); | |
| if (ulReturn == 1) | |
| IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb); | |
| return ulReturn; | |
| } | |
| static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface) | |
| { | |
| ICOM_THIS(IDirectSound3DBufferImpl,iface); | |
| ULONG ulReturn; | |
| TRACE("(%p) ref was %ld\n", This, This->ref); | |
| ulReturn = InterlockedDecrement(&This->ref); | |
| if(ulReturn) | |
| return ulReturn; | |
| if (This->dsb) { | |
| BOOL std = (This->dsb->dsbd.dwFlags & DSBCAPS_CTRL3D); | |
| IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb); | |
| if (std) | |
| return 0; /* leave it to IDirectSoundBufferImpl_Release */ | |
| } | |
| if (This->dsb->ds3db == This) This->dsb->ds3db = NULL; | |
| DeleteCriticalSection(&This->lock); | |
| HeapFree(GetProcessHeap(),0,This); | |
| return 0; | |
| } | |
| /* IDirectSound3DBuffer methods */ | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPDS3DBUFFER lpDs3dBuffer) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPDWORD lpdwInsideConeAngle, | |
| LPDWORD lpdwOutsideConeAngle) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPD3DVECTOR lpvConeOrientation) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPLONG lplConeOutsideVolume) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPD3DVALUE lpfMaxDistance) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPD3DVALUE lpfMinDistance) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPDWORD lpdwMode) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPD3DVECTOR lpvPosition) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPD3DVECTOR lpvVelocity) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LPCDS3DBUFFER lpcDs3dBuffer, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| DWORD dwInsideConeAngle, | |
| DWORD dwOutsideConeAngle, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| LONG lConeOutsideVolume, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| D3DVALUE fMaxDistance, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| D3DVALUE fMinDistance, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| DWORD dwMode, | |
| DWORD dwApply) | |
| { | |
| ICOM_THIS(IDirectSound3DBufferImpl,iface); | |
| TRACE("mode = %lx\n", dwMode); | |
| This->ds3db.dwMode = dwMode; | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity( | |
| LPDIRECTSOUND3DBUFFER iface, | |
| D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static ICOM_VTABLE(IDirectSound3DBuffer) ds3dbvt = | |
| { | |
| ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE | |
| /* IUnknown methods */ | |
| IDirectSound3DBufferImpl_QueryInterface, | |
| IDirectSound3DBufferImpl_AddRef, | |
| IDirectSound3DBufferImpl_Release, | |
| /* IDirectSound3DBuffer methods */ | |
| IDirectSound3DBufferImpl_GetAllParameters, | |
| IDirectSound3DBufferImpl_GetConeAngles, | |
| IDirectSound3DBufferImpl_GetConeOrientation, | |
| IDirectSound3DBufferImpl_GetConeOutsideVolume, | |
| IDirectSound3DBufferImpl_GetMaxDistance, | |
| IDirectSound3DBufferImpl_GetMinDistance, | |
| IDirectSound3DBufferImpl_GetMode, | |
| IDirectSound3DBufferImpl_GetPosition, | |
| IDirectSound3DBufferImpl_GetVelocity, | |
| IDirectSound3DBufferImpl_SetAllParameters, | |
| IDirectSound3DBufferImpl_SetConeAngles, | |
| IDirectSound3DBufferImpl_SetConeOrientation, | |
| IDirectSound3DBufferImpl_SetConeOutsideVolume, | |
| IDirectSound3DBufferImpl_SetMaxDistance, | |
| IDirectSound3DBufferImpl_SetMinDistance, | |
| IDirectSound3DBufferImpl_SetMode, | |
| IDirectSound3DBufferImpl_SetPosition, | |
| IDirectSound3DBufferImpl_SetVelocity, | |
| }; | |
| HRESULT WINAPI IDirectSound3DBufferImpl_Create( | |
| IDirectSoundBufferImpl *This, | |
| IDirectSound3DBufferImpl **pds3db) | |
| { | |
| IDirectSound3DBufferImpl *ds3db; | |
| ds3db = (IDirectSound3DBufferImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*ds3db)); | |
| ds3db->ref = 0; | |
| ds3db->dsb = This; | |
| ICOM_VTBL(ds3db) = &ds3dbvt; | |
| InitializeCriticalSection(&ds3db->lock); | |
| ds3db->ds3db.dwSize = sizeof(DS3DBUFFER); | |
| ds3db->ds3db.vPosition.u1.x = 0.0; | |
| ds3db->ds3db.vPosition.u2.y = 0.0; | |
| ds3db->ds3db.vPosition.u3.z = 0.0; | |
| ds3db->ds3db.vVelocity.u1.x = 0.0; | |
| ds3db->ds3db.vVelocity.u2.y = 0.0; | |
| ds3db->ds3db.vVelocity.u3.z = 0.0; | |
| ds3db->ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE; | |
| ds3db->ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE; | |
| ds3db->ds3db.vConeOrientation.u1.x = 0.0; | |
| ds3db->ds3db.vConeOrientation.u2.y = 0.0; | |
| ds3db->ds3db.vConeOrientation.u3.z = 0.0; | |
| ds3db->ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME; | |
| ds3db->ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE; | |
| ds3db->ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE; | |
| ds3db->ds3db.dwMode = DS3DMODE_NORMAL; | |
| *pds3db = ds3db; | |
| return S_OK; | |
| } | |
| /******************************************************************************* | |
| * IDirectSound3DListener | |
| */ | |
| /* IUnknown methods */ | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface( | |
| LPDIRECTSOUND3DLISTENER iface, REFIID riid, LPVOID *ppobj) | |
| { | |
| ICOM_THIS(IDirectSound3DListenerImpl,iface); | |
| TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); | |
| return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj); | |
| } | |
| static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface) | |
| { | |
| ICOM_THIS(IDirectSound3DListenerImpl,iface); | |
| return InterlockedIncrement(&This->ref); | |
| } | |
| static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface) | |
| { | |
| ICOM_THIS(IDirectSound3DListenerImpl,iface); | |
| ULONG ulReturn; | |
| TRACE("(%p) ref was %ld\n", This, This->ref); | |
| ulReturn = InterlockedDecrement(&This->ref); | |
| /* Free all resources */ | |
| if( ulReturn == 0 ) { | |
| if(This->dsb) | |
| IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb); | |
| DeleteCriticalSection(&This->lock); | |
| HeapFree(GetProcessHeap(),0,This); | |
| } | |
| return ulReturn; | |
| } | |
| /* IDirectSound3DListener methods */ | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| LPDS3DLISTENER lpDS3DL) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| LPD3DVALUE lpfDistanceFactor) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| LPD3DVALUE lpfDopplerFactor) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| LPD3DVECTOR lpvOrientFront, | |
| LPD3DVECTOR lpvOrientTop) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| LPD3DVECTOR lpvPosition) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| LPD3DVALUE lpfRolloffFactor) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| LPD3DVECTOR lpvVelocity) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| LPCDS3DLISTENER lpcDS3DL, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| D3DVALUE fDistanceFactor, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| D3DVALUE fDopplerFactor, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront, | |
| D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| D3DVALUE fRolloffFactor, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity( | |
| LPDIRECTSOUND3DLISTENER iface, | |
| D3DVALUE x, D3DVALUE y, D3DVALUE z, | |
| DWORD dwApply) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings( | |
| LPDIRECTSOUND3DLISTENER iface) | |
| { | |
| FIXME("stub\n"); | |
| return DS_OK; | |
| } | |
| static ICOM_VTABLE(IDirectSound3DListener) ds3dlvt = | |
| { | |
| ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE | |
| /* IUnknown methods */ | |
| IDirectSound3DListenerImpl_QueryInterface, | |
| IDirectSound3DListenerImpl_AddRef, | |
| IDirectSound3DListenerImpl_Release, | |
| /* IDirectSound3DListener methods */ | |
| IDirectSound3DListenerImpl_GetAllParameter, | |
| IDirectSound3DListenerImpl_GetDistanceFactor, | |
| IDirectSound3DListenerImpl_GetDopplerFactor, | |
| IDirectSound3DListenerImpl_GetOrientation, | |
| IDirectSound3DListenerImpl_GetPosition, | |
| IDirectSound3DListenerImpl_GetRolloffFactor, | |
| IDirectSound3DListenerImpl_GetVelocity, | |
| IDirectSound3DListenerImpl_SetAllParameters, | |
| IDirectSound3DListenerImpl_SetDistanceFactor, | |
| IDirectSound3DListenerImpl_SetDopplerFactor, | |
| IDirectSound3DListenerImpl_SetOrientation, | |
| IDirectSound3DListenerImpl_SetPosition, | |
| IDirectSound3DListenerImpl_SetRolloffFactor, | |
| IDirectSound3DListenerImpl_SetVelocity, | |
| IDirectSound3DListenerImpl_CommitDeferredSettings, | |
| }; | |
| HRESULT WINAPI IDirectSound3DListenerImpl_Create( | |
| PrimaryBufferImpl *This, | |
| IDirectSound3DListenerImpl **pdsl) | |
| { | |
| IDirectSound3DListenerImpl *dsl; | |
| dsl = (IDirectSound3DListenerImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsl)); | |
| dsl->ref = 1; | |
| ICOM_VTBL(dsl) = &ds3dlvt; | |
| dsl->ds3dl.dwSize = sizeof(DS3DLISTENER); | |
| dsl->ds3dl.vPosition.u1.x = 0.0; | |
| dsl->ds3dl.vPosition.u2.y = 0.0; | |
| dsl->ds3dl.vPosition.u3.z = 0.0; | |
| dsl->ds3dl.vVelocity.u1.x = 0.0; | |
| dsl->ds3dl.vVelocity.u2.y = 0.0; | |
| dsl->ds3dl.vVelocity.u3.z = 0.0; | |
| dsl->ds3dl.vOrientFront.u1.x = 0.0; | |
| dsl->ds3dl.vOrientFront.u2.y = 0.0; | |
| dsl->ds3dl.vOrientFront.u3.z = 1.0; | |
| dsl->ds3dl.vOrientTop.u1.x = 0.0; | |
| dsl->ds3dl.vOrientTop.u2.y = 1.0; | |
| dsl->ds3dl.vOrientTop.u3.z = 0.0; | |
| dsl->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR; | |
| dsl->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR; | |
| InitializeCriticalSection(&dsl->lock); | |
| dsl->dsb = This; | |
| IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This); | |
| *pdsl = dsl; | |
| return S_OK; | |
| } |