mirror of
https://github.com/reactos/reactos.git
synced 2024-08-20 02:13:29 +00:00
511 lines
13 KiB
C
511 lines
13 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Configuration of network devices
|
|
* FILE: dll/directx/dsound_new/directsound.c
|
|
* PURPOSE: Handles IDirectSound interface
|
|
*
|
|
* PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
typedef struct
|
|
{
|
|
IDirectSound8Vtbl *lpVtbl;
|
|
LONG ref;
|
|
GUID DeviceGUID;
|
|
BOOL bInitialized;
|
|
BOOL bDirectSound8;
|
|
DWORD dwLevel;
|
|
LPFILTERINFO Filter;
|
|
LPDIRECTSOUNDBUFFER8 PrimaryBuffer;
|
|
|
|
|
|
}CDirectSoundImpl, *LPCDirectSoundImpl;
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnQueryInterface(
|
|
LPDIRECTSOUND8 iface,
|
|
REFIID riid,
|
|
LPVOID * ppobj)
|
|
{
|
|
LPOLESTR pStr;
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
if ((IsEqualIID(riid, &IID_IDirectSound) && This->bDirectSound8 == FALSE) ||
|
|
(IsEqualIID(riid, &IID_IDirectSound8) && This->bDirectSound8 != FALSE) ||
|
|
(IsEqualIID(riid, &IID_IUnknown)))
|
|
{
|
|
*ppobj = (LPVOID)&This->lpVtbl;
|
|
InterlockedIncrement(&This->ref);
|
|
return S_OK;
|
|
}
|
|
|
|
if (SUCCEEDED(StringFromIID(riid, &pStr)))
|
|
{
|
|
DPRINT("No Interface for class %s\n", pStr);
|
|
CoTaskMemFree(pStr);
|
|
}
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
ULONG
|
|
WINAPI
|
|
IDirectSound8_fnAddRef(
|
|
LPDIRECTSOUND8 iface)
|
|
{
|
|
ULONG ref;
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
ref = InterlockedIncrement(&This->ref);
|
|
|
|
return ref;
|
|
}
|
|
|
|
ULONG
|
|
WINAPI
|
|
IDirectSound8_fnRelease(
|
|
LPDIRECTSOUND8 iface)
|
|
{
|
|
ULONG ref;
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
ref = InterlockedDecrement(&(This->ref));
|
|
|
|
if (!ref)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, This);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnCreateSoundBuffer(
|
|
LPDIRECTSOUND8 iface,
|
|
LPCDSBUFFERDESC lpcDSBufferDesc,
|
|
LPLPDIRECTSOUNDBUFFER lplpDirectSoundBuffer,
|
|
IUnknown FAR* pUnkOuter)
|
|
{
|
|
HRESULT hResult;
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
if (!This->bInitialized)
|
|
{
|
|
/* object not yet initialized */
|
|
return DSERR_UNINITIALIZED;
|
|
}
|
|
|
|
if (!lpcDSBufferDesc || !lplpDirectSoundBuffer || pUnkOuter != NULL)
|
|
{
|
|
DPRINT("Invalid parameter %p %p %p\n", lpcDSBufferDesc, lplpDirectSoundBuffer, pUnkOuter);
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
/* check buffer description */
|
|
if ((lpcDSBufferDesc->dwSize != sizeof(DSBUFFERDESC) && lpcDSBufferDesc->dwSize != sizeof(DSBUFFERDESC1)) || lpcDSBufferDesc->dwReserved != 0)
|
|
{
|
|
DPRINT("Invalid buffer description size %u expected %u dwReserved %u\n", lpcDSBufferDesc->dwSize, sizeof(DSBUFFERDESC1), lpcDSBufferDesc->dwReserved);
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
DPRINT("This %p dwFlags %x dwBufferBytes %u lpwfxFormat %p dwSize %u\n", This, lpcDSBufferDesc->dwFlags, lpcDSBufferDesc->dwBufferBytes, lpcDSBufferDesc->lpwfxFormat, lpcDSBufferDesc->dwSize);
|
|
|
|
if (lpcDSBufferDesc->dwFlags & DSBCAPS_PRIMARYBUFFER)
|
|
{
|
|
if (lpcDSBufferDesc->lpwfxFormat != NULL)
|
|
{
|
|
/* format must be null for primary sound buffer */
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
if (lpcDSBufferDesc->dwBufferBytes != 0)
|
|
{
|
|
/* buffer size must be zero for primary sound buffer */
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
if (This->PrimaryBuffer)
|
|
{
|
|
/* primary buffer already exists */
|
|
IDirectSoundBuffer8_AddRef(This->PrimaryBuffer);
|
|
*lplpDirectSoundBuffer = (LPDIRECTSOUNDBUFFER)This->PrimaryBuffer;
|
|
return S_OK;
|
|
}
|
|
|
|
hResult = NewPrimarySoundBuffer((LPLPDIRECTSOUNDBUFFER8)lplpDirectSoundBuffer, This->Filter, This->dwLevel, lpcDSBufferDesc->dwFlags);
|
|
if (SUCCEEDED(hResult))
|
|
{
|
|
/* store primary buffer */
|
|
This->PrimaryBuffer = (LPDIRECTSOUNDBUFFER8)*lplpDirectSoundBuffer;
|
|
}
|
|
return hResult;
|
|
}
|
|
else
|
|
{
|
|
if (lpcDSBufferDesc->lpwfxFormat == NULL)
|
|
{
|
|
/* format must not be null */
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
if (lpcDSBufferDesc->dwBufferBytes < DSBSIZE_MIN || lpcDSBufferDesc->dwBufferBytes > DSBSIZE_MAX)
|
|
{
|
|
/* buffer size must be within bounds for secondary sound buffer*/
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
if (!This->PrimaryBuffer)
|
|
{
|
|
hResult = NewPrimarySoundBuffer((LPLPDIRECTSOUNDBUFFER8)lplpDirectSoundBuffer, This->Filter, This->dwLevel, lpcDSBufferDesc->dwFlags);
|
|
if (SUCCEEDED(hResult))
|
|
{
|
|
/* store primary buffer */
|
|
This->PrimaryBuffer = (LPDIRECTSOUNDBUFFER8)*lplpDirectSoundBuffer;
|
|
}
|
|
else
|
|
{
|
|
DPRINT("Failed to create primary buffer with %x\n", hResult);
|
|
return hResult;
|
|
}
|
|
|
|
}
|
|
|
|
ASSERT(This->PrimaryBuffer);
|
|
|
|
DPRINT("This %p wFormatTag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u NBlockAlign %u wBitsPerSample %u cbSize %u\n",
|
|
This, lpcDSBufferDesc->lpwfxFormat->wFormatTag, lpcDSBufferDesc->lpwfxFormat->nChannels, lpcDSBufferDesc->lpwfxFormat->nSamplesPerSec, lpcDSBufferDesc->lpwfxFormat->nAvgBytesPerSec, lpcDSBufferDesc->lpwfxFormat->nBlockAlign, lpcDSBufferDesc->lpwfxFormat->wBitsPerSample, lpcDSBufferDesc->lpwfxFormat->cbSize);
|
|
|
|
hResult = NewSecondarySoundBuffer((LPLPDIRECTSOUNDBUFFER8)lplpDirectSoundBuffer, This->Filter, This->dwLevel, lpcDSBufferDesc, This->PrimaryBuffer);
|
|
return hResult;
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnGetCaps(
|
|
LPDIRECTSOUND8 iface,
|
|
LPDSCAPS lpDSCaps)
|
|
{
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
if (!This->bInitialized)
|
|
{
|
|
/* object not yet initialized */
|
|
return DSERR_UNINITIALIZED;
|
|
}
|
|
|
|
if (!lpDSCaps)
|
|
{
|
|
/* object not yet initialized */
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
if (lpDSCaps->dwSize != sizeof(DSCAPS))
|
|
{
|
|
/* object not yet initialized */
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
UNIMPLEMENTED;
|
|
return DSERR_GENERIC;
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnDuplicateSoundBuffer(
|
|
LPDIRECTSOUND8 iface,
|
|
LPDIRECTSOUNDBUFFER lpDsbOriginal,
|
|
LPLPDIRECTSOUNDBUFFER lplpDsbDuplicate)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return DSERR_OUTOFMEMORY;
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnSetCooperativeLevel(
|
|
LPDIRECTSOUND8 iface,
|
|
HWND hwnd,
|
|
DWORD dwLevel)
|
|
{
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
if (!This->bInitialized)
|
|
{
|
|
/* object not yet initialized */
|
|
return DSERR_UNINITIALIZED;
|
|
}
|
|
|
|
/* store cooperation level */
|
|
This->dwLevel = dwLevel;
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnCompact(
|
|
LPDIRECTSOUND8 iface)
|
|
{
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
if (!This->bInitialized)
|
|
{
|
|
/* object not yet initialized */
|
|
return DSERR_UNINITIALIZED;
|
|
}
|
|
|
|
if (This->dwLevel != DSSCL_PRIORITY)
|
|
{
|
|
/* needs priority level */
|
|
return DSERR_PRIOLEVELNEEDED;
|
|
}
|
|
|
|
/* done */
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnGetSpeakerConfig(
|
|
LPDIRECTSOUND8 iface,
|
|
LPDWORD pdwSpeakerConfig)
|
|
{
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
if (!This->bInitialized)
|
|
{
|
|
/* object not yet initialized */
|
|
return DSERR_UNINITIALIZED;
|
|
}
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnSetSpeakerConfig(
|
|
LPDIRECTSOUND8 iface,
|
|
DWORD dwSpeakerConfig)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnInitialize(
|
|
LPDIRECTSOUND8 iface,
|
|
LPCGUID pcGuidDevice)
|
|
{
|
|
GUID DeviceGuid;
|
|
LPOLESTR pGuidStr;
|
|
HRESULT hr;
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
if (!RootInfo)
|
|
{
|
|
EnumAudioDeviceInterfaces(&RootInfo);
|
|
}
|
|
|
|
/* sanity check */
|
|
ASSERT(RootInfo);
|
|
|
|
if (This->bInitialized)
|
|
{
|
|
/* object has already been initialized */
|
|
return DSERR_ALREADYINITIALIZED;
|
|
}
|
|
|
|
/* fixme mutual exclusion */
|
|
|
|
if (pcGuidDevice == NULL || IsEqualGUID(pcGuidDevice, &GUID_NULL))
|
|
{
|
|
/* use default playback device id */
|
|
pcGuidDevice = &DSDEVID_DefaultPlayback;
|
|
}
|
|
|
|
if (IsEqualIID(pcGuidDevice, &DSDEVID_DefaultCapture) || IsEqualIID(pcGuidDevice, &DSDEVID_DefaultVoiceCapture))
|
|
{
|
|
/* this has to be a winetest */
|
|
return DSERR_NODRIVER;
|
|
}
|
|
|
|
/* now verify the guid */
|
|
if (GetDeviceID(pcGuidDevice, &DeviceGuid) != DS_OK)
|
|
{
|
|
if (SUCCEEDED(StringFromIID(pcGuidDevice, &pGuidStr)))
|
|
{
|
|
DPRINT("IDirectSound8_fnInitialize: Unknown GUID %ws\n", pGuidStr);
|
|
CoTaskMemFree(pGuidStr);
|
|
}
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
hr = FindDeviceByGuid(&DeviceGuid, &This->Filter);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
This->bInitialized = TRUE;
|
|
return DS_OK;
|
|
}
|
|
|
|
DPRINT("Failed to find device\n");
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
IDirectSound8_fnVerifyCertification(
|
|
LPDIRECTSOUND8 iface,
|
|
LPDWORD pdwCertified)
|
|
{
|
|
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
|
|
|
if (!This->bInitialized)
|
|
{
|
|
/* object not yet initialized */
|
|
return DSERR_UNINITIALIZED;
|
|
}
|
|
|
|
UNIMPLEMENTED;
|
|
return DS_CERTIFIED;
|
|
}
|
|
|
|
static IDirectSound8Vtbl vt_DirectSound8 =
|
|
{
|
|
/* IUnknown methods */
|
|
IDirectSound8_fnQueryInterface,
|
|
IDirectSound8_fnAddRef,
|
|
IDirectSound8_fnRelease,
|
|
/* IDirectSound methods */
|
|
IDirectSound8_fnCreateSoundBuffer,
|
|
IDirectSound8_fnGetCaps,
|
|
IDirectSound8_fnDuplicateSoundBuffer,
|
|
IDirectSound8_fnSetCooperativeLevel,
|
|
IDirectSound8_fnCompact,
|
|
IDirectSound8_fnGetSpeakerConfig,
|
|
IDirectSound8_fnSetSpeakerConfig,
|
|
IDirectSound8_fnInitialize,
|
|
/* IDirectSound8 methods */
|
|
IDirectSound8_fnVerifyCertification
|
|
};
|
|
|
|
HRESULT
|
|
InternalDirectSoundCreate(
|
|
LPCGUID lpcGUID,
|
|
LPDIRECTSOUND8 *ppDS,
|
|
IUnknown *pUnkOuter,
|
|
BOOL bDirectSound8)
|
|
{
|
|
LPCDirectSoundImpl This;
|
|
HRESULT hr;
|
|
|
|
if (!ppDS || pUnkOuter != NULL)
|
|
{
|
|
/* invalid parameter passed */
|
|
return DSERR_INVALIDPARAM;
|
|
}
|
|
|
|
/* allocate CDirectSoundImpl struct */
|
|
This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundImpl));
|
|
if (!This)
|
|
{
|
|
/* not enough memory */
|
|
return DSERR_OUTOFMEMORY;
|
|
}
|
|
|
|
/* initialize IDirectSound object */
|
|
This->ref = 1;
|
|
This->bDirectSound8 = bDirectSound8;
|
|
This->lpVtbl = &vt_DirectSound8;
|
|
|
|
|
|
/* initialize direct sound interface */
|
|
hr = IDirectSound8_Initialize((LPDIRECTSOUND8)&This->lpVtbl, lpcGUID);
|
|
|
|
/* check for success */
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
/* failed */
|
|
DPRINT("Failed to initialize DirectSound object with %x\n", hr);
|
|
IDirectSound8_Release((LPDIRECTSOUND8)&This->lpVtbl);
|
|
return hr;
|
|
}
|
|
|
|
/* store result */
|
|
*ppDS = (LPDIRECTSOUND8)&This->lpVtbl;
|
|
DPRINT("DirectSound object %p\n", *ppDS);
|
|
return DS_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CALLBACK
|
|
NewDirectSound(
|
|
IUnknown* pUnkOuter,
|
|
REFIID riid,
|
|
LPVOID* ppvObject)
|
|
{
|
|
LPOLESTR pStr;
|
|
LPCDirectSoundImpl This;
|
|
|
|
/* check param */
|
|
if (!ppvObject)
|
|
{
|
|
/* invalid param */
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
/* check requested interface */
|
|
if (!IsEqualIID(riid, &IID_IUnknown) && !IsEqualIID(riid, &IID_IDirectSound) && !IsEqualIID(riid, &IID_IDirectSound8))
|
|
{
|
|
*ppvObject = 0;
|
|
StringFromIID(riid, &pStr);
|
|
DPRINT("KsPropertySet does not support Interface %ws\n", pStr);
|
|
CoTaskMemFree(pStr);
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
/* allocate CDirectSoundCaptureImpl struct */
|
|
This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundImpl));
|
|
if (!This)
|
|
{
|
|
/* not enough memory */
|
|
return DSERR_OUTOFMEMORY;
|
|
}
|
|
|
|
/* initialize object */
|
|
This->ref = 1;
|
|
This->lpVtbl = &vt_DirectSound8;
|
|
This->bInitialized = FALSE;
|
|
*ppvObject = (LPVOID)&This->lpVtbl;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
WINAPI
|
|
DirectSoundCreate(
|
|
LPCGUID lpcGUID,
|
|
LPDIRECTSOUND *ppDS,
|
|
IUnknown *pUnkOuter)
|
|
{
|
|
return InternalDirectSoundCreate(lpcGUID, (LPDIRECTSOUND8*)ppDS, pUnkOuter, FALSE);
|
|
}
|
|
|
|
HRESULT
|
|
WINAPI
|
|
DirectSoundCreate8(
|
|
LPCGUID lpcGUID,
|
|
LPDIRECTSOUND8 *ppDS,
|
|
IUnknown *pUnkOuter)
|
|
{
|
|
return InternalDirectSoundCreate(lpcGUID, ppDS, pUnkOuter, TRUE);
|
|
}
|