From: Mark Harmstone Subject: [PATCH 2/2] xaudio2_7: add IXAudio2 stub Message-Id: <54B2ADAC.7020909@burntcomma.com> Date: Sun, 11 Jan 2015 17:06:52 +0000 --- dlls/xaudio2_7/Makefile.in | 4 +- dlls/xaudio2_7/xaudio.c | 182 ++++++++++++++++++++++++++++++++++++++++ dlls/xaudio2_7/xaudio.idl | 22 +++++ dlls/xaudio2_7/xaudio_dll.c | 173 +++++++++++++++++++++++++++++++++++++- dlls/xaudio2_7/xaudio_private.h | 12 +++ 5 files changed, 391 insertions(+), 2 deletions(-) create mode 100644 dlls/xaudio2_7/xaudio.c create mode 100644 dlls/xaudio2_7/xaudio.idl create mode 100644 dlls/xaudio2_7/xaudio_private.h diff --git a/dlls/xaudio2_7/Makefile.in b/dlls/xaudio2_7/Makefile.in index 5dbe40b..d882e46 100644 --- a/dlls/xaudio2_7/Makefile.in +++ b/dlls/xaudio2_7/Makefile.in @@ -1,5 +1,7 @@ MODULE = xaudio2_7.dll IMPORTS = advapi32 kernel32 ole32 user32 uuid +IDL_SRCS = xaudio.idl + C_SRCS = \ - xaudio_dll.c + xaudio_dll.c xaudio.c diff --git a/dlls/xaudio2_7/xaudio.c b/dlls/xaudio2_7/xaudio.c new file mode 100644 index 0000000..76aaea3 --- /dev/null +++ b/dlls/xaudio2_7/xaudio.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2015 Mark Harmstone + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#define NONAMELESSUNION + +#include "xaudio_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(xaudio2); + +static inline IXAudio2Impl *impl_from_IXAudio2(IXAudio2 *iface) +{ + return CONTAINING_RECORD(iface, IXAudio2Impl, IXAudio2_iface); +} + +static HRESULT WINAPI XAudio2_QueryInterface(IXAudio2* This, REFIID riid, void** ppobj) +{ + TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj); + + if (ppobj == NULL) + return E_POINTER; + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IXAudio2)) + { + *ppobj = This; + IXAudio2_AddRef(This); + return S_OK; + } + + *ppobj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI XAudio2_AddRef(IXAudio2* This) +{ + IXAudio2Impl *impl = impl_from_IXAudio2(This); + + TRACE("(%p)\n", This); + + return InterlockedIncrement(&impl->refcount); +} + +static ULONG WINAPI XAudio2_Release(IXAudio2* This) +{ + IXAudio2Impl *impl = impl_from_IXAudio2(This); + ULONG ret = InterlockedDecrement(&impl->refcount); + + TRACE("(%p)\n", This); + + if (ret == 0) + HeapFree(GetProcessHeap(), 0, This); + + return ret; +} + +static HRESULT WINAPI XAudio2_GetDeviceCount(IXAudio2* This, UINT32* count) +{ + FIXME("(%p, %p) stub\n", This, count); + + return E_NOTIMPL; +} + +static HRESULT WINAPI XAudio2_GetDeviceDetails(IXAudio2* This, UINT32 index, XAUDIO2_DEVICE_DETAILS* details) +{ + FIXME("(%p, %u, %p) stub\n", This, index, details); + + return E_NOTIMPL; +} + +static HRESULT WINAPI XAudio2_Initialize(IXAudio2* This, UINT32 flags, XAUDIO2_PROCESSOR processor) +{ + FIXME("(%p, %u, %u) stub\n", This, flags, processor); + + return S_OK; +} + +static HRESULT WINAPI XAudio2_RegisterForCallbacks(IXAudio2* This, IXAudio2EngineCallback* callback) +{ + FIXME("(%p, %p) stub\n", This, callback); + + return E_NOTIMPL; +} + +static void WINAPI XAudio2_UnregisterForCallbacks(IXAudio2* This, IXAudio2EngineCallback* callback) +{ + FIXME("(%p, %p) stub\n", This, callback); +} + +static HRESULT WINAPI XAudio2_CreateSourceVoice(IXAudio2* This, IXAudio2SourceVoice** psourcevoice, + const WAVEFORMATEX* format, UINT32 flags, float maxfreqratio, + IXAudio2VoiceCallback* callback, const XAUDIO2_VOICE_SENDS* sendlist, + const XAUDIO2_EFFECT_CHAIN* effectchain) +{ + FIXME("(%p, %p, %p, %u, %f, %p, %p, %p) stub\n", This, psourcevoice, format, flags, maxfreqratio, callback, sendlist, effectchain); + + return E_NOTIMPL; +} + +static HRESULT WINAPI XAudio2_CreateSubmixVoice(IXAudio2* This, IXAudio2SubmixVoice** psubmixvoice, + UINT32 channels, UINT32 samplerate, UINT32 flags, + UINT32 processingstage, const XAUDIO2_VOICE_SENDS* sendlist, + const XAUDIO2_EFFECT_CHAIN* effectchain) +{ + FIXME("(%p, %p, %u, %u, %u, %u, %p, %p) stub\n", This, psubmixvoice, channels, samplerate, flags, processingstage, sendlist, effectchain); + + return E_NOTIMPL; +} + +static HRESULT WINAPI XAudio2_CreateMasteringVoice(IXAudio2* This, IXAudio2MasteringVoice** pmasteringvoice, + UINT32 channels, UINT32 samplerate, UINT32 flags, + UINT32 deviceindex, const XAUDIO2_EFFECT_CHAIN* effectchain) +{ + FIXME("(%p, %p, %u, %u, %u, %u, %p) stub\n", This, pmasteringvoice, channels, samplerate, flags, deviceindex, effectchain); + + return E_NOTIMPL; +} + +static HRESULT WINAPI XAudio2_StartEngine(IXAudio2* This) +{ + FIXME("(%p) stub\n", This); + + return E_NOTIMPL; +} + +static void WINAPI XAudio2_StopEngine(IXAudio2* This) +{ + FIXME("(%p) stub\n", This); +} + +static HRESULT WINAPI XAudio2_CommitChanges(IXAudio2* This, UINT32 operationset) +{ + FIXME("(%p, %u) stub\n", This, operationset); + + return E_NOTIMPL; +} + +static void WINAPI XAudio2_GetPerformanceData(IXAudio2* This, XAUDIO2_PERFORMANCE_DATA* perfdata) +{ + FIXME("(%p, %p) stub\n", This, perfdata); +} + +static void WINAPI XAudio2_SetDebugConfiguration(IXAudio2* This, const XAUDIO2_DEBUG_CONFIGURATION* debugconf, void* reserved) +{ + FIXME("(%p, %p, %p) stub\n", This, debugconf, reserved); +} + +const IXAudio2Vtbl XAudio_Vtbl = { + XAudio2_QueryInterface, + XAudio2_AddRef, + XAudio2_Release, + XAudio2_GetDeviceCount, + XAudio2_GetDeviceDetails, + XAudio2_Initialize, + XAudio2_RegisterForCallbacks, + XAudio2_UnregisterForCallbacks, + XAudio2_CreateSourceVoice, + XAudio2_CreateSubmixVoice, + XAudio2_CreateMasteringVoice, + XAudio2_StartEngine, + XAudio2_StopEngine, + XAudio2_CommitChanges, + XAudio2_GetPerformanceData, + XAudio2_SetDebugConfiguration +}; diff --git a/dlls/xaudio2_7/xaudio.idl b/dlls/xaudio2_7/xaudio.idl new file mode 100644 index 0000000..36a437d --- /dev/null +++ b/dlls/xaudio2_7/xaudio.idl @@ -0,0 +1,22 @@ +#pragma makedep register + +import "unknwn.idl"; +import "mmdeviceapi.idl"; + +[ + helpstring("XAudio2"), + threading(both), + uuid(5a508685-a254-4fba-9b82-9a24b00306af) +] +coclass XAudio2 { + interface IUnknown; +} + +[ + helpstring("XAudio2 (debug version)"), + threading(both), + uuid(db05ea35-0329-4d4b-a53a-6dead03d3852) +] +coclass XAudio2Debug { + interface IUnknown; +} diff --git a/dlls/xaudio2_7/xaudio_dll.c b/dlls/xaudio2_7/xaudio_dll.c index ef52834..0211732 100644 --- a/dlls/xaudio2_7/xaudio_dll.c +++ b/dlls/xaudio2_7/xaudio_dll.c @@ -30,12 +30,36 @@ #include "wine/debug.h" #include #include "initguid.h" -#include "xaudio2.h" +#include "xaudio_private.h" WINE_DEFAULT_DEBUG_CHANNEL(xaudio2); +DEFINE_GUID(CLSID_XAudio27, 0x5a508685, 0xa254, 0x4fba, 0x9b,0x82, 0x9a,0x24,0xb0,0x03,0x06,0xaf); +DEFINE_GUID(CLSID_XAudio27_Debug, 0xdb05ea35, 0x0329, 0x4d4b, 0xa5,0x3a, 0x6d,0xea,0xd0,0x3d,0x38,0x52); + +typedef enum { + type_XAudio2, + type_AudioReverb, + type_AudioVolumeMeter +} FactoryType; + +typedef struct { + const CLSID* clsid; + int version; + FactoryType type; + BOOL debug; +} class_table; + +const class_table ClassTable[] = { + { &CLSID_XAudio27, 7, type_XAudio2, FALSE }, + { &CLSID_XAudio27_Debug, 7, type_XAudio2, TRUE }, + { NULL, 0, 0, FALSE } +}; + static HINSTANCE instance; +LONG XAUDIO_refcount = 0; + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); @@ -54,11 +78,136 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) HRESULT WINAPI DllCanUnloadNow(void) { + return XAUDIO_refcount!=0 ? S_FALSE : S_OK; +} + +typedef struct { + IClassFactory IClassFactory_iface; + REFCLSID rclsid; + int ref; + FactoryType type; + int version; + BOOL debug; +} IClassFactoryImpl; + +static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) +{ + return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); +} + +static HRESULT WINAPI XAudioCF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppobj) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj); + if (ppobj == NULL) + return E_POINTER; + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IClassFactory)) + { + *ppobj = iface; + IClassFactory_AddRef(iface); + return S_OK; + } + *ppobj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI XAudioCF_AddRef(LPCLASSFACTORY iface) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI XAudioCF_Release(LPCLASSFACTORY iface) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + ULONG ret = InterlockedDecrement(&This->ref); + + if (ret == 0) { + HeapFree(GetProcessHeap(), 0, This); + XAUDIO_refcount--; + } + + return ret; +} + +static HRESULT WINAPI XAudioCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, + REFIID riid, LPVOID *ppobj) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + TRACE("(%p, %p, %s, %p)\n", This, pOuter, debugstr_guid(riid), ppobj); + + if (pOuter) + return CLASS_E_NOAGGREGATION; + + if (ppobj == NULL) { + WARN("invalid parameter\n"); + return E_POINTER; + } + + if (This->type == type_XAudio2 && IsEqualIID(riid, &IID_IXAudio2)) { + IXAudio2Impl* impl; + + impl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IXAudio2Impl)); + impl->IXAudio2_iface.lpVtbl = &XAudio_Vtbl; + impl->version = This->version; + impl->debug = This->debug; + + *ppobj = impl; + + IXAudio2_AddRef((IXAudio2*)impl); + + return S_OK; + } + + *ppobj = NULL; + + return E_NOINTERFACE; +} + +static HRESULT WINAPI XAudioCF_LockServer(LPCLASSFACTORY iface, BOOL dolock) +{ + if (dolock) + InterlockedIncrement(&XAUDIO_refcount); + else + InterlockedDecrement(&XAUDIO_refcount); + return S_OK; } +static const IClassFactoryVtbl XAudioCF_Vtbl = { + XAudioCF_QueryInterface, + XAudioCF_AddRef, + XAudioCF_Release, + XAudioCF_CreateInstance, + XAudioCF_LockServer +}; + +static BOOL examine_clsid(REFCLSID rclsid, FactoryType* type, int* version, BOOL* debug) +{ + int i; + + i = 0; + while (ClassTable[i].clsid) { + if (IsEqualCLSID(ClassTable[i].clsid, rclsid)) { + *type = ClassTable[i].type; + *version = ClassTable[i].version; + *debug = ClassTable[i].debug; + + return TRUE; + } + i++; + } + + return FALSE; +} + HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) { + BOOL debug; + int version; + FactoryType type; + TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); if (ppv == NULL) { @@ -68,6 +217,28 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) *ppv = NULL; + if (!IsEqualIID(riid, &IID_IClassFactory) && + !IsEqualIID(riid, &IID_IUnknown)) { + WARN("no interface for %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; + } + + if (examine_clsid(rclsid, &type, &version, &debug)) { + IClassFactoryImpl *impl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IClassFactoryImpl)); + impl->IClassFactory_iface.lpVtbl = &XAudioCF_Vtbl; + impl->type = type; + impl->version = version; + impl->debug = debug; + + TRACE("Created class factory %p\n", impl); + + IClassFactory_AddRef((IClassFactory*)impl); + + *ppv = impl; + XAUDIO_refcount++; + return S_OK; + } + WARN("(%s, %s, %p): no class found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/xaudio2_7/xaudio_private.h b/dlls/xaudio2_7/xaudio_private.h new file mode 100644 index 0000000..f6d9e2f --- /dev/null +++ b/dlls/xaudio2_7/xaudio_private.h @@ -0,0 +1,12 @@ +#include "xaudio2.h" + +typedef struct { + IXAudio2 IXAudio2_iface; + + int refcount; + int version; + BOOL debug; +} IXAudio2Impl; + +const IXAudio2Vtbl XAudio_Vtbl; +