xaudio2: Implement IXAudio2::GetDeviceDetails.
This commit is contained in:
parent
8027a5268e
commit
cc22fdaf4e
|
@ -17824,6 +17824,7 @@ wine_fn_config_dll xapofx1_3 enable_xapofx1_3
|
|||
wine_fn_config_dll xapofx1_4 enable_xapofx1_4
|
||||
wine_fn_config_dll xapofx1_5 enable_xapofx1_5
|
||||
wine_fn_config_dll xaudio2_7 enable_xaudio2_7 clean
|
||||
wine_fn_config_test dlls/xaudio2_7/tests xaudio2_7_test
|
||||
wine_fn_config_dll xaudio2_8 enable_xaudio2_8
|
||||
wine_fn_config_dll xinput1_1 enable_xinput1_1
|
||||
wine_fn_config_dll xinput1_2 enable_xinput1_2
|
||||
|
|
|
@ -3425,6 +3425,7 @@ WINE_CONFIG_DLL(xapofx1_3)
|
|||
WINE_CONFIG_DLL(xapofx1_4)
|
||||
WINE_CONFIG_DLL(xapofx1_5)
|
||||
WINE_CONFIG_DLL(xaudio2_7,,[clean])
|
||||
WINE_CONFIG_TEST(dlls/xaudio2_7/tests)
|
||||
WINE_CONFIG_DLL(xaudio2_8)
|
||||
WINE_CONFIG_DLL(xinput1_1)
|
||||
WINE_CONFIG_DLL(xinput1_2)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
TESTDLL = xaudio2_7.dll
|
||||
IMPORTS = ole32
|
||||
|
||||
C_SRCS = \
|
||||
xaudio2.c
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Andrew Eikum for CodeWeavers
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define COBJMACROS
|
||||
#include "wine/test.h"
|
||||
#include "initguid.h"
|
||||
#include "xaudio2.h"
|
||||
|
||||
static BOOL xaudio27;
|
||||
|
||||
static HRESULT (WINAPI *pXAudio2Create)(IXAudio2 **, UINT32, XAUDIO2_PROCESSOR) = NULL;
|
||||
|
||||
static void test_DeviceDetails(IXAudio27 *xa)
|
||||
{
|
||||
HRESULT hr;
|
||||
XAUDIO2_DEVICE_DETAILS dd;
|
||||
UINT32 count, i;
|
||||
|
||||
hr = IXAudio27_GetDeviceCount(xa, &count);
|
||||
ok(hr == S_OK, "GetDeviceCount failed: %08x\n", hr);
|
||||
|
||||
if(count == 0)
|
||||
return;
|
||||
|
||||
for(i = 0; i < count; ++i){
|
||||
hr = IXAudio27_GetDeviceDetails(xa, i, &dd);
|
||||
ok(hr == S_OK, "GetDeviceDetails failed: %08x\n", hr);
|
||||
|
||||
if(i == 0)
|
||||
ok(dd.Role == GlobalDefaultDevice, "Got wrong role for index 0: 0x%x\n", dd.Role);
|
||||
else
|
||||
ok(dd.Role == NotDefaultDevice, "Got wrong role for index %u: 0x%x\n", i, dd.Role);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(xaudio2)
|
||||
{
|
||||
HRESULT hr;
|
||||
IXAudio27 *xa27 = NULL;
|
||||
IXAudio2 *xa = NULL;
|
||||
HANDLE xa28dll;
|
||||
|
||||
CoInitialize(NULL);
|
||||
|
||||
xa28dll = LoadLibraryA("xaudio2_8.dll");
|
||||
if(xa28dll)
|
||||
pXAudio2Create = (void*)GetProcAddress(xa28dll, "XAudio2Create");
|
||||
|
||||
/* XAudio 2.7 (Jun 2010 DirectX) */
|
||||
hr = CoCreateInstance(&CLSID_XAudio2, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IXAudio27, (void**)&xa27);
|
||||
if(hr == S_OK){
|
||||
xaudio27 = TRUE;
|
||||
|
||||
hr = IXAudio27_Initialize(xa27, 0, XAUDIO2_ANY_PROCESSOR);
|
||||
ok(hr == S_OK, "Initialize failed: %08x\n", hr);
|
||||
|
||||
test_DeviceDetails(xa27);
|
||||
|
||||
IXAudio27_Release(xa27);
|
||||
}else
|
||||
win_skip("XAudio 2.7 not available\n");
|
||||
|
||||
/* XAudio 2.8 (Win8+) */
|
||||
if(pXAudio2Create){
|
||||
xaudio27 = FALSE;
|
||||
|
||||
hr = pXAudio2Create(&xa, 0, XAUDIO2_DEFAULT_PROCESSOR);
|
||||
ok(hr == S_OK, "XAudio2Create failed: %08x\n", hr);
|
||||
|
||||
IXAudio2_Release(xa);
|
||||
}else
|
||||
win_skip("XAudio 2.8 not available\n");
|
||||
|
||||
CoUninitialize();
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Mark Harmstone
|
||||
* Copyright (c) 2015 Andrew Eikum for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -18,6 +19,8 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
#define COBJMACROS
|
||||
|
||||
#include "windef.h"
|
||||
|
@ -34,6 +37,9 @@
|
|||
|
||||
#include "mmsystem.h"
|
||||
#include "xaudio2.h"
|
||||
#include "devpkey.h"
|
||||
#include "mmdeviceapi.h"
|
||||
#include "audioclient.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(xaudio2);
|
||||
|
||||
|
@ -155,6 +161,11 @@ typedef struct {
|
|||
|
||||
struct list source_voices;
|
||||
struct list submix_voices;
|
||||
|
||||
IMMDeviceEnumerator *devenum;
|
||||
|
||||
WCHAR **devids;
|
||||
UINT32 ndevs;
|
||||
} IXAudio2Impl;
|
||||
|
||||
static inline IXAudio2Impl *impl_from_IXAudio2(IXAudio2 *iface)
|
||||
|
@ -1098,6 +1109,7 @@ static ULONG WINAPI IXAudio2Impl_Release(IXAudio2 *iface)
|
|||
TRACE("(%p)->(): Refcount now %u\n", This, ref);
|
||||
|
||||
if (!ref) {
|
||||
int i;
|
||||
XA2SourceImpl *src, *src2;
|
||||
XA2SubmixImpl *sub, *sub2;
|
||||
|
||||
|
@ -1113,6 +1125,12 @@ static ULONG WINAPI IXAudio2Impl_Release(IXAudio2 *iface)
|
|||
HeapFree(GetProcessHeap(), 0, sub);
|
||||
}
|
||||
|
||||
if(This->devenum)
|
||||
IMMDeviceEnumerator_Release(This->devenum);
|
||||
for(i = 0; i < This->ndevs; ++i)
|
||||
CoTaskMemFree(This->devids[i]);
|
||||
HeapFree(GetProcessHeap(), 0, This->devids);
|
||||
|
||||
DeleteCriticalSection(&This->lock);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
|
@ -1365,16 +1383,93 @@ static ULONG WINAPI XA27_Release(IXAudio27 *iface)
|
|||
static HRESULT WINAPI XA27_GetDeviceCount(IXAudio27 *iface, UINT32 *pCount)
|
||||
{
|
||||
IXAudio2Impl *This = impl_from_IXAudio27(iface);
|
||||
TRACE("(%p)->(%p)\n", This, pCount);
|
||||
return E_NOTIMPL;
|
||||
|
||||
TRACE("%p, %p\n", This, pCount);
|
||||
|
||||
*pCount = This->ndevs;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI XA27_GetDeviceDetails(IXAudio27 *iface, UINT32 index,
|
||||
XAUDIO2_DEVICE_DETAILS *pDeviceDetails)
|
||||
{
|
||||
IXAudio2Impl *This = impl_from_IXAudio27(iface);
|
||||
TRACE("(%p)->(%u, %p)\n", This, index, pDeviceDetails);
|
||||
return E_NOTIMPL;
|
||||
HRESULT hr;
|
||||
IMMDevice *dev;
|
||||
IAudioClient *client;
|
||||
IPropertyStore *ps;
|
||||
WAVEFORMATEX *wfx;
|
||||
PROPVARIANT var;
|
||||
|
||||
TRACE("%p, %u, %p\n", This, index, pDeviceDetails);
|
||||
|
||||
if(index >= This->ndevs)
|
||||
return E_INVALIDARG;
|
||||
|
||||
hr = IMMDeviceEnumerator_GetDevice(This->devenum, This->devids[index], &dev);
|
||||
if(FAILED(hr)){
|
||||
WARN("GetDevice failed: %08x\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
|
||||
NULL, (void**)&client);
|
||||
if(FAILED(hr)){
|
||||
WARN("Activate failed: %08x\n", hr);
|
||||
IMMDevice_Release(dev);
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = IMMDevice_OpenPropertyStore(dev, STGM_READ, &ps);
|
||||
if(FAILED(hr)){
|
||||
WARN("OpenPropertyStore failed: %08x\n", hr);
|
||||
IAudioClient_Release(client);
|
||||
IMMDevice_Release(dev);
|
||||
return hr;
|
||||
}
|
||||
|
||||
PropVariantInit(&var);
|
||||
|
||||
hr = IPropertyStore_GetValue(ps, (PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &var);
|
||||
if(FAILED(hr)){
|
||||
WARN("GetValue failed: %08x\n", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
lstrcpynW(pDeviceDetails->DisplayName, var.u.pwszVal, sizeof(pDeviceDetails->DisplayName)/sizeof(WCHAR));
|
||||
|
||||
PropVariantClear(&var);
|
||||
|
||||
hr = IAudioClient_GetMixFormat(client, &wfx);
|
||||
if(FAILED(hr)){
|
||||
WARN("GetMixFormat failed: %08x\n", hr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
lstrcpyW(pDeviceDetails->DeviceID, This->devids[index]);
|
||||
|
||||
if(index == 0)
|
||||
pDeviceDetails->Role = GlobalDefaultDevice;
|
||||
else
|
||||
pDeviceDetails->Role = NotDefaultDevice;
|
||||
|
||||
if(sizeof(WAVEFORMATEX) + wfx->cbSize > sizeof(pDeviceDetails->OutputFormat)){
|
||||
FIXME("AudioClient format is too large to fit into WAVEFORMATEXTENSIBLE!\n");
|
||||
CoTaskMemFree(wfx);
|
||||
hr = E_FAIL;
|
||||
goto done;
|
||||
}
|
||||
memcpy(&pDeviceDetails->OutputFormat, wfx, sizeof(WAVEFORMATEX) + wfx->cbSize);
|
||||
|
||||
CoTaskMemFree(wfx);
|
||||
|
||||
done:
|
||||
IPropertyStore_Release(ps);
|
||||
IAudioClient_Release(client);
|
||||
IMMDevice_Release(dev);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI XA27_Initialize(IXAudio27 *iface, UINT32 flags,
|
||||
|
@ -1429,12 +1524,16 @@ static HRESULT WINAPI XA27_CreateMasteringVoice(IXAudio27 *iface,
|
|||
const XAUDIO2_EFFECT_CHAIN *pEffectChain)
|
||||
{
|
||||
IXAudio2Impl *This = impl_from_IXAudio27(iface);
|
||||
|
||||
TRACE("(%p)->(%p, %u, %u, 0x%x, %u, %p)\n", This, ppMasteringVoice,
|
||||
inputChannels, inputSampleRate, flags, deviceIndex,
|
||||
pEffectChain);
|
||||
/* TODO: Convert DeviceIndex to DeviceId */
|
||||
return IXAudio2Impl_CreateMasteringVoice(&This->IXAudio2_iface,
|
||||
ppMasteringVoice, inputChannels, inputSampleRate, flags, 0,
|
||||
|
||||
if(deviceIndex >= This->ndevs)
|
||||
return E_INVALIDARG;
|
||||
|
||||
return IXAudio2Impl_CreateMasteringVoice(&This->IXAudio2_iface, ppMasteringVoice,
|
||||
inputChannels, inputSampleRate, flags, This->devids[deviceIndex],
|
||||
pEffectChain, AudioCategory_GameEffects);
|
||||
}
|
||||
|
||||
|
@ -1516,6 +1615,79 @@ static ULONG WINAPI XAudio2CF_Release(IClassFactory *iface)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static HRESULT initialize_mmdevices(IXAudio2Impl *This)
|
||||
{
|
||||
IMMDeviceCollection *devcoll;
|
||||
UINT devcount;
|
||||
HRESULT hr;
|
||||
|
||||
if(!This->devenum){
|
||||
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
|
||||
CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&This->devenum);
|
||||
if(FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = IMMDeviceEnumerator_EnumAudioEndpoints(This->devenum, eRender,
|
||||
DEVICE_STATE_ACTIVE, &devcoll);
|
||||
if(FAILED(hr)){
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = IMMDeviceCollection_GetCount(devcoll, &devcount);
|
||||
if(FAILED(hr)){
|
||||
IMMDeviceCollection_Release(devcoll);
|
||||
return hr;
|
||||
}
|
||||
|
||||
if(devcount > 0){
|
||||
UINT i, count = 1;
|
||||
IMMDevice *dev, *def_dev;
|
||||
|
||||
/* make sure that device 0 is the default device */
|
||||
IMMDeviceEnumerator_GetDefaultAudioEndpoint(This->devenum, eRender, eConsole, &def_dev);
|
||||
|
||||
This->devids = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * devcount);
|
||||
|
||||
for(i = 0; i < devcount; ++i){
|
||||
hr = IMMDeviceCollection_Item(devcoll, i, &dev);
|
||||
if(SUCCEEDED(hr)){
|
||||
UINT idx;
|
||||
|
||||
if(dev == def_dev)
|
||||
idx = 0;
|
||||
else{
|
||||
idx = count;
|
||||
++count;
|
||||
}
|
||||
|
||||
hr = IMMDevice_GetId(dev, &This->devids[idx]);
|
||||
if(FAILED(hr)){
|
||||
WARN("GetId failed: %08x\n", hr);
|
||||
HeapFree(GetProcessHeap(), 0, This->devids);
|
||||
This->devids = NULL;
|
||||
IMMDevice_Release(dev);
|
||||
return hr;
|
||||
}
|
||||
|
||||
IMMDevice_Release(dev);
|
||||
}else{
|
||||
WARN("Item failed: %08x\n", hr);
|
||||
HeapFree(GetProcessHeap(), 0, This->devids);
|
||||
This->devids = NULL;
|
||||
IMMDeviceCollection_Release(devcoll);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IMMDeviceCollection_Release(devcoll);
|
||||
|
||||
This->ndevs = devcount;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
|
||||
REFIID riid, void **ppobj)
|
||||
{
|
||||
|
@ -1549,8 +1721,17 @@ static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *p
|
|||
object->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IXAudio2Impl.lock");
|
||||
|
||||
hr = IXAudio2_QueryInterface(&object->IXAudio2_iface, riid, ppobj);
|
||||
if(FAILED(hr))
|
||||
if(FAILED(hr)){
|
||||
HeapFree(GetProcessHeap(), 0, object);
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = initialize_mmdevices(object);
|
||||
if(FAILED(hr)){
|
||||
IUnknown_Release((IUnknown*)*ppobj);
|
||||
return hr;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue