diff --git a/dlls/xaudio2_7/tests/xaudio2.c b/dlls/xaudio2_7/tests/xaudio2.c index 949a5cf9f96..0538f80c072 100644 --- a/dlls/xaudio2_7/tests/xaudio2.c +++ b/dlls/xaudio2_7/tests/xaudio2.c @@ -23,11 +23,14 @@ #include "wine/test.h" #include "initguid.h" #include "xaudio2.h" +#include "xaudio2fx.h" +#include "xapo.h" #include "mmsystem.h" static BOOL xaudio27; static HRESULT (WINAPI *pXAudio2Create)(IXAudio2 **, UINT32, XAUDIO2_PROCESSOR) = NULL; +static HRESULT (WINAPI *pCreateAudioVolumeMeter)(IUnknown**) = NULL; #define XA2CALL_0(method) if(xaudio27) hr = IXAudio27_##method((IXAudio27*)xa); else hr = IXAudio2_##method(xa); #define XA2CALL_0V(method) if(xaudio27) IXAudio27_##method((IXAudio27*)xa); else IXAudio2_##method(xa); @@ -165,9 +168,12 @@ static void test_simple_streaming(IXAudio2 *xa) HRESULT hr; IXAudio2MasteringVoice *master; IXAudio2SourceVoice *src, *src2; + IUnknown *vumeter; WAVEFORMATEX fmt; XAUDIO2_BUFFER buf, buf2; XAUDIO2_VOICE_STATE state; + XAUDIO2_EFFECT_DESCRIPTOR effect; + XAUDIO2_EFFECT_CHAIN chain; memset(&ecb_state, 0, sizeof(ecb_state)); memset(&src1_state, 0, sizeof(src1_state)); @@ -190,6 +196,7 @@ static void test_simple_streaming(IXAudio2 *xa) hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects); ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr); + /* create first source voice */ fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; fmt.nChannels = 2; fmt.nSamplesPerSec = 44100; @@ -212,7 +219,7 @@ static void test_simple_streaming(IXAudio2 *xa) hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW); ok(hr == S_OK, "Start failed: %08x\n", hr); - + /* create second source voice */ XA2CALL(CreateSourceVoice, &src2, &fmt, 0, 1.f, &vcb2, NULL, NULL); ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr); @@ -230,6 +237,28 @@ static void test_simple_streaming(IXAudio2 *xa) XA2CALL_0(StartEngine); ok(hr == S_OK, "StartEngine failed: %08x\n", hr); + /* hook up volume meter */ + if(xaudio27){ + hr = CoCreateInstance(&CLSID_AudioVolumeMeter, NULL, + CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&vumeter); + ok(hr == S_OK, "CoCreateInstance(AudioVolumeMeter) failed: %08x\n", hr); + }else{ + hr = pCreateAudioVolumeMeter(&vumeter); + ok(hr == S_OK, "CreateAudioVolumeMeter failed: %08x\n", hr); + } + + effect.InitialState = TRUE; + effect.OutputChannels = 2; + effect.pEffect = vumeter; + + chain.EffectCount = 1; + chain.pEffectDescriptors = &effect; + + hr = IXAudio2MasteringVoice_SetEffectChain(master, &chain); + ok(hr == S_OK, "SetEffectchain failed: %08x\n", hr); + + IUnknown_Release(vumeter); + while(1){ if(xaudio27) IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state); @@ -471,8 +500,10 @@ START_TEST(xaudio2) CoInitialize(NULL); xa28dll = LoadLibraryA("xaudio2_8.dll"); - if(xa28dll) + if(xa28dll){ pXAudio2Create = (void*)GetProcAddress(xa28dll, "XAudio2Create"); + pCreateAudioVolumeMeter = (void*)GetProcAddress(xa28dll, "CreateAudioVolumeMeter"); + } /* XAudio 2.7 (Jun 2010 DirectX) */ hr = CoCreateInstance(&CLSID_XAudio2, NULL, CLSCTX_INPROC_SERVER, diff --git a/dlls/xaudio2_7/xaudio_classes.idl b/dlls/xaudio2_7/xaudio_classes.idl index 79bc7a4cab8..a39d082da9a 100644 --- a/dlls/xaudio2_7/xaudio_classes.idl +++ b/dlls/xaudio2_7/xaudio_classes.idl @@ -26,3 +26,10 @@ uuid(5a508685-a254-4fba-9b82-9a24b00306af) ] coclass XAudio2 { interface IXAudio2; } + +[ + helpstring("XAudio2 Volume Meter Class"), + threading(both), + uuid(cac1105f-619b-4d04-831a-44e1cbf12d57) +] +coclass AudioVolumeMeter { interface IUnknown; } diff --git a/dlls/xaudio2_7/xaudio_dll.c b/dlls/xaudio2_7/xaudio_dll.c index 453645bbb1f..7a5f45b2e0b 100644 --- a/dlls/xaudio2_7/xaudio_dll.c +++ b/dlls/xaudio2_7/xaudio_dll.c @@ -36,6 +36,8 @@ #include "mmsystem.h" #include "xaudio2.h" +#include "xaudio2fx.h" +#include "xapo.h" #include "devpkey.h" #include "mmdeviceapi.h" #include "audioclient.h" @@ -2231,6 +2233,208 @@ static const IXAudio27Vtbl XAudio27_Vtbl = { XA27_SetDebugConfiguration }; +typedef struct _VUMeterImpl { + IXAPO IXAPO_iface; + IXAPOParameters IXAPOParameters_iface; + + LONG ref; +} VUMeterImpl; + +static VUMeterImpl *VUMeterImpl_from_IXAPO(IXAPO *iface) +{ + return CONTAINING_RECORD(iface, VUMeterImpl, IXAPO_iface); +} + +static VUMeterImpl *VUMeterImpl_from_IXAPOParameters(IXAPOParameters *iface) +{ + return CONTAINING_RECORD(iface, VUMeterImpl, IXAPOParameters_iface); +} + +static HRESULT WINAPI VUMXAPO_QueryInterface(IXAPO *iface, REFIID riid, + void **ppvObject) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + + TRACE("%p, %s, %p\n", This, wine_dbgstr_guid(riid), ppvObject); + + if(IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IXAPO) || + IsEqualGUID(riid, &IID_IXAPO27)) + *ppvObject = &This->IXAPO_iface; + else if(IsEqualGUID(riid, &IID_IXAPOParameters)) + *ppvObject = &This->IXAPOParameters_iface; + else + *ppvObject = NULL; + + if(*ppvObject){ + IUnknown_AddRef((IUnknown*)*ppvObject); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI VUMXAPO_AddRef(IXAPO *iface) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p)->(): Refcount now %u\n", This, ref); + return ref; +} + +static ULONG WINAPI VUMXAPO_Release(IXAPO *iface) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(): Refcount now %u\n", This, ref); + + if(!ref) + HeapFree(GetProcessHeap(), 0, This); + + return ref; +} + +static HRESULT WINAPI VUMXAPO_GetRegistrationProperties(IXAPO *iface, + XAPO_REGISTRATION_PROPERTIES **props) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p, %p\n", This, props); + return E_NOTIMPL; +} + +static HRESULT WINAPI VUMXAPO_IsInputFormatSupported(IXAPO *iface, + const WAVEFORMATEX *output_fmt, const WAVEFORMATEX *input_fmt, + WAVEFORMATEX **supported_fmt) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p, %p, %p, %p\n", This, output_fmt, input_fmt, supported_fmt); + return E_NOTIMPL; +} + +static HRESULT WINAPI VUMXAPO_IsOutputFormatSupported(IXAPO *iface, + const WAVEFORMATEX *input_fmt, const WAVEFORMATEX *output_fmt, + WAVEFORMATEX **supported_fmt) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p, %p, %p, %p\n", This, input_fmt, output_fmt, supported_fmt); + return E_NOTIMPL; +} + +static HRESULT WINAPI VUMXAPO_Initialize(IXAPO *iface, const void *data, + UINT32 data_len) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p, %p, %u\n", This, data, data_len); + return E_NOTIMPL; +} + +static HRESULT WINAPI VUMXAPO_Reset(IXAPO *iface) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI VUMXAPO_LockForProcess(IXAPO *iface, + UINT32 in_params_count, + const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *in_params, + UINT32 out_params_count, + const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *out_params) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p, %u, %p, %u, %p\n", This, in_params_count, in_params, + out_params_count, out_params); + return E_NOTIMPL; +} + +static void WINAPI VUMXAPO_UnlockForProcess(IXAPO *iface) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p\n", This); +} + +static void WINAPI VUMXAPO_Process(IXAPO *iface, UINT32 in_params_count, + const XAPO_PROCESS_BUFFER_PARAMETERS *in_params, + UINT32 out_params_count, + const XAPO_PROCESS_BUFFER_PARAMETERS *out_params, BOOL enabled) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p, %u, %p, %u, %p, %u\n", This, in_params_count, in_params, + out_params_count, out_params, enabled); +} + +static UINT32 WINAPI VUMXAPO_CalcInputFrames(IXAPO *iface, UINT32 output_frames) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p, %u\n", This, output_frames); + return 0; +} + +static UINT32 WINAPI VUMXAPO_CalcOutputFrames(IXAPO *iface, UINT32 input_frames) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPO(iface); + TRACE("%p, %u\n", This, input_frames); + return 0; +} + +static const IXAPOVtbl VUMXAPO_Vtbl = { + VUMXAPO_QueryInterface, + VUMXAPO_AddRef, + VUMXAPO_Release, + VUMXAPO_GetRegistrationProperties, + VUMXAPO_IsInputFormatSupported, + VUMXAPO_IsOutputFormatSupported, + VUMXAPO_Initialize, + VUMXAPO_Reset, + VUMXAPO_LockForProcess, + VUMXAPO_UnlockForProcess, + VUMXAPO_Process, + VUMXAPO_CalcInputFrames, + VUMXAPO_CalcOutputFrames +}; + +static HRESULT WINAPI VUMXAPOParams_QueryInterface(IXAPOParameters *iface, + REFIID riid, void **ppvObject) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPOParameters(iface); + return VUMXAPO_QueryInterface(&This->IXAPO_iface, riid, ppvObject); +} + +static ULONG WINAPI VUMXAPOParams_AddRef(IXAPOParameters *iface) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPOParameters(iface); + return VUMXAPO_AddRef(&This->IXAPO_iface); +} + +static ULONG WINAPI VUMXAPOParams_Release(IXAPOParameters *iface) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPOParameters(iface); + return VUMXAPO_Release(&This->IXAPO_iface); +} + +static void WINAPI VUMXAPOParams_SetParameters(IXAPOParameters *iface, + const void *params, UINT32 params_len) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPOParameters(iface); + TRACE("%p, %p, %u\n", This, params, params_len); +} + +static void WINAPI VUMXAPOParams_GetParameters(IXAPOParameters *iface, + void *params, UINT32 params_len) +{ + VUMeterImpl *This = VUMeterImpl_from_IXAPOParameters(iface); + TRACE("%p, %p, %u\n", This, params, params_len); +} + +static const IXAPOParametersVtbl VUMXAPOParameters_Vtbl = { + VUMXAPOParams_QueryInterface, + VUMXAPOParams_AddRef, + VUMXAPOParams_Release, + VUMXAPOParams_SetParameters, + VUMXAPOParams_GetParameters +}; + static HRESULT WINAPI XAudio2CF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj) { if(IsEqualGUID(riid, &IID_IUnknown) @@ -2382,6 +2586,35 @@ static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *p return hr; } +static HRESULT WINAPI VUMeterCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter, + REFIID riid, void **ppobj) +{ + HRESULT hr; + VUMeterImpl *object; + + TRACE("(static)->(%p,%s,%p)\n", pOuter, debugstr_guid(riid), ppobj); + + *ppobj = NULL; + + if(pOuter) + return CLASS_E_NOAGGREGATION; + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); + if(!object) + return E_OUTOFMEMORY; + + object->IXAPO_iface.lpVtbl = &VUMXAPO_Vtbl; + object->IXAPOParameters_iface.lpVtbl = &VUMXAPOParameters_Vtbl; + + hr = IXAPO_QueryInterface(&object->IXAPO_iface, riid, ppobj); + if(FAILED(hr)){ + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + return S_OK; +} + static HRESULT WINAPI XAudio2CF_LockServer(IClassFactory *iface, BOOL dolock) { FIXME("(static)->(%d): stub!\n", dolock); @@ -2397,7 +2630,17 @@ static const IClassFactoryVtbl XAudio2CF_Vtbl = XAudio2CF_LockServer }; +static const IClassFactoryVtbl VUMeterCF_Vtbl = +{ + XAudio2CF_QueryInterface, + XAudio2CF_AddRef, + XAudio2CF_Release, + VUMeterCF_CreateInstance, + XAudio2CF_LockServer +}; + static IClassFactory xaudio2_cf = { &XAudio2CF_Vtbl }; +static IClassFactory vumeter_cf = { &VUMeterCF_Vtbl }; HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { @@ -2407,6 +2650,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) if(IsEqualGUID(rclsid, &CLSID_XAudio2)) { factory = &xaudio2_cf; + }else if(IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter)) { + factory = &vumeter_cf; } if(!factory) return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/xaudio2_8/xaudio2_8.spec b/dlls/xaudio2_8/xaudio2_8.spec index dd4fee15f76..3228d71f3d3 100644 --- a/dlls/xaudio2_8/xaudio2_8.spec +++ b/dlls/xaudio2_8/xaudio2_8.spec @@ -1 +1,2 @@ @ stdcall XAudio2Create(ptr long long) +@ stdcall CreateAudioVolumeMeter(ptr) diff --git a/dlls/xaudio2_8/xaudio_dll.c b/dlls/xaudio2_8/xaudio_dll.c index e5dfb9d4344..521cc29cd70 100644 --- a/dlls/xaudio2_8/xaudio_dll.c +++ b/dlls/xaudio2_8/xaudio_dll.c @@ -26,6 +26,8 @@ #include "initguid.h" #include "xaudio2.h" +#include "xaudio2fx.h" +#include "xapo.h" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { @@ -71,3 +73,9 @@ HRESULT WINAPI XAudio2Create(IXAudio2 **ppxa2, UINT32 flags, XAUDIO2_PROCESSOR p return S_OK; } + +HRESULT WINAPI CreateAudioVolumeMeter(IUnknown **out) +{ + return CoCreateInstance(&CLSID_AudioVolumeMeter, NULL, CLSCTX_INPROC_SERVER, + &IID_IUnknown, (void**)out); +} diff --git a/include/Makefile.in b/include/Makefile.in index 9ed76637331..b1104eee42c 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -147,6 +147,7 @@ PUBLIC_IDL_H_SRCS = \ wuapi.idl \ xapo.idl \ xaudio2.idl \ + xaudio2fx.idl \ xmllite.idl IDL_TLB_SRCS = \ diff --git a/include/xaudio2fx.idl b/include/xaudio2fx.idl new file mode 100644 index 00000000000..8d74264c9a7 --- /dev/null +++ b/include/xaudio2fx.idl @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 Andrew Eikum + * + * 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 + */ + +import "unknwn.idl"; + +[ + uuid(cac1105f-619b-4d04-831a-44e1cbf12d57) +] +coclass AudioVolumeMeter { + interface IUnknown; +}