From: David McFarland corngood@gmail.com
--- dlls/mmdevapi/Makefile.in | 1 + dlls/mmdevapi/devenum.c | 2 +- dlls/mmdevapi/devicetopology.c | 322 +++++++++++++++++++++++++++ dlls/mmdevapi/mmdevapi_private.h | 1 + dlls/mmdevapi/tests/devicetopology.c | 1 - 5 files changed, 325 insertions(+), 2 deletions(-) create mode 100644 dlls/mmdevapi/devicetopology.c
diff --git a/dlls/mmdevapi/Makefile.in b/dlls/mmdevapi/Makefile.in index d9ec97b87e5..a380e28f61d 100644 --- a/dlls/mmdevapi/Makefile.in +++ b/dlls/mmdevapi/Makefile.in @@ -6,6 +6,7 @@ C_SRCS = \ audiovolume.c \ client.c \ devenum.c \ + devicetopology.c \ main.c \ session.c \ spatialaudio.c diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c index 2900d222795..5077da64466 100644 --- a/dlls/mmdevapi/devenum.c +++ b/dlls/mmdevapi/devenum.c @@ -689,7 +689,7 @@ static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD cls } else if (IsEqualIID(riid, &IID_IDeviceTopology)) { - FIXME("IID_IDeviceTopology unsupported\n"); + hr = DeviceTopology_Create(iface, (IDeviceTopology**)ppv); } else if (IsEqualIID(riid, &IID_IDirectSound) || IsEqualIID(riid, &IID_IDirectSound8)) diff --git a/dlls/mmdevapi/devicetopology.c b/dlls/mmdevapi/devicetopology.c new file mode 100644 index 00000000000..e23701695c9 --- /dev/null +++ b/dlls/mmdevapi/devicetopology.c @@ -0,0 +1,322 @@ +/* + * 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 + +#include <audiopolicy.h> +#include <mmdeviceapi.h> + +#include <wine/debug.h> + +#include "mmdevapi_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi); + +struct connector { + IConnector IConnector_iface; + + LONG ref; +}; + +static inline struct connector *impl_from_IConnector(IConnector *iface) +{ + return CONTAINING_RECORD(iface, struct connector, IConnector_iface); +} + +static HRESULT WINAPI connector_QueryInterface(IConnector *iface, REFIID riid, void **ppv) +{ + struct connector *This = impl_from_IConnector(iface); + TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); + + if (!ppv) + return E_POINTER; + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IConnector)) + *ppv = &This->IConnector_iface; + else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*ppv); + + return S_OK; +} + +static ULONG WINAPI connector_AddRef(IConnector *iface) +{ + struct connector *This = impl_from_IConnector(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) new ref %lu\n", This, ref); + return ref; +} + +static ULONG WINAPI connector_Release(IConnector *iface) +{ + struct connector *This = impl_from_IConnector(iface); + ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p) new ref %lu\n", This, ref); + + if (!ref) + HeapFree(GetProcessHeap(), 0, This); + + return ref; +} + +static HRESULT WINAPI connector_GetType( + IConnector *This, + ConnectorType *pType) +{ + FIXME("(%p) - partial stub\n", This); + *pType = Physical_Internal; + return S_OK; +} + +static HRESULT WINAPI connector_GetDataFlow( + IConnector *This, + DataFlow *pFlow) +{ + FIXME("(%p) - stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI connector_ConnectTo( + IConnector *This, + IConnector *pConnectTo) +{ + FIXME("(%p) - stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI connector_Disconnect( + IConnector *This) +{ + FIXME("(%p) - stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI connector_IsConnected( + IConnector *This, + BOOL *pbConnected) +{ + FIXME("(%p) - stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI connector_GetConnectedTo( + IConnector *This, + IConnector **ppConTo) +{ + FIXME("(%p) - stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI connector_GetConnectorIdConnectedTo( + IConnector *This, + LPWSTR *ppwstrConnectorId) +{ + FIXME("(%p) - stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI connector_GetDeviceIdConnectedTo( + IConnector *This, + LPWSTR *ppwstrDeviceId) +{ + FIXME("(%p) - stub\n", This); + return E_NOTIMPL; +} + +static const IConnectorVtbl Connector_Vtbl = +{ + connector_QueryInterface, + connector_AddRef, + connector_Release, + connector_GetType, + connector_GetDataFlow, + connector_ConnectTo, + connector_Disconnect, + connector_IsConnected, + connector_GetConnectedTo, + connector_GetConnectorIdConnectedTo, + connector_GetDeviceIdConnectedTo, +}; + +HRESULT connector_Create(IConnector **ppv) +{ + struct connector *This; + + This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This)); + if (!This) + return E_OUTOFMEMORY; + + This->IConnector_iface.lpVtbl = &Connector_Vtbl; + This->ref = 1; + + *ppv = &This->IConnector_iface; + + return S_OK; +} + +struct device_topology { + IDeviceTopology IDeviceTopology_iface; + + LONG ref; +}; + +static inline struct device_topology *impl_from_IDeviceTopology(IDeviceTopology *iface) +{ + return CONTAINING_RECORD(iface, struct device_topology, IDeviceTopology_iface); +} + +static HRESULT WINAPI DT_QueryInterface(IDeviceTopology *iface, REFIID riid, void **ppv) +{ + struct device_topology *This = impl_from_IDeviceTopology(iface); + TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); + + if (!ppv) + return E_POINTER; + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IDeviceTopology)) + *ppv = &This->IDeviceTopology_iface; + else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*ppv); + + return S_OK; +} + +static ULONG WINAPI DT_AddRef(IDeviceTopology *iface) +{ + struct device_topology *This = impl_from_IDeviceTopology(iface); + ULONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) new ref %lu\n", This, ref); + return ref; +} + +static ULONG WINAPI DT_Release(IDeviceTopology *iface) +{ + struct device_topology *This = impl_from_IDeviceTopology(iface); + ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p) new ref %lu\n", This, ref); + + if (!ref) + HeapFree(GetProcessHeap(), 0, This); + + return ref; +} + +static HRESULT WINAPI DT_GetConnectorCount(IDeviceTopology *This, + UINT *pCount) +{ + FIXME("(%p)->(%p) - partial stub\n", This, pCount); + + if (!pCount) + return E_POINTER; + + *pCount = 1; + return S_OK; +} + +static HRESULT WINAPI DT_GetConnector(IDeviceTopology *This, + UINT nIndex, + IConnector **ppConnector) +{ + FIXME("(%p)->(%u, %p) - partial stub\n", This, nIndex, ppConnector); + + if (nIndex == 0) + { + return connector_Create(ppConnector); + } + + return E_INVALIDARG; +} + +static HRESULT WINAPI DT_GetSubunitCount(IDeviceTopology *This, + UINT *pCount) +{ + FIXME("(%p)->(%p) - stub\n", This, pCount); + return E_NOTIMPL; +} + +static HRESULT WINAPI DT_GetSubunit(IDeviceTopology *This, + UINT nIndex, + ISubUnit **ppConnector) +{ + FIXME("(%p)->(%u, %p) - stub\n", This, nIndex, ppConnector); + return E_NOTIMPL; +} + +static HRESULT WINAPI DT_GetPartById(IDeviceTopology *This, + UINT nId, + IPart **ppPart) +{ + FIXME("(%p)->(%u, %p) - stub\n", This, nId, ppPart); + return E_NOTIMPL; +} + +static HRESULT WINAPI DT_GetDeviceId(IDeviceTopology *This, + LPWSTR *ppwstrDeviceId) +{ + FIXME("(%p)->(%p) - stub\n", This, ppwstrDeviceId); + return E_NOTIMPL; +} + +static HRESULT WINAPI DT_GetSignalPath(IDeviceTopology *This, + IPart *pIPartFrom, + IPart *pIPartTo, + BOOL bRejectMixedPaths, + IPartsList **ppParts) +{ + FIXME("(%p)->(%p, %p, %s, %p) - stub\n", + This, pIPartFrom, pIPartTo, bRejectMixedPaths ? "TRUE" : "FALSE", ppParts); + return E_NOTIMPL; +} + +static const IDeviceTopologyVtbl DeviceTopology_Vtbl = +{ + DT_QueryInterface, + DT_AddRef, + DT_Release, + DT_GetConnectorCount, + DT_GetConnector, + DT_GetSubunitCount, + DT_GetSubunit, + DT_GetPartById, + DT_GetDeviceId, + DT_GetSignalPath, +}; + +HRESULT DeviceTopology_Create(IMMDevice *device, IDeviceTopology **ppv) +{ + struct device_topology *This; + + This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This)); + if (!This) + return E_OUTOFMEMORY; + + This->IDeviceTopology_iface.lpVtbl = &DeviceTopology_Vtbl; + This->ref = 1; + + *ppv = &This->IDeviceTopology_iface; + + return S_OK; +} diff --git a/dlls/mmdevapi/mmdevapi_private.h b/dlls/mmdevapi/mmdevapi_private.h index 0ed9140c3ed..b96e99df96f 100644 --- a/dlls/mmdevapi/mmdevapi_private.h +++ b/dlls/mmdevapi/mmdevapi_private.h @@ -73,6 +73,7 @@ extern HRESULT AudioClient_Create(GUID *guid, IMMDevice *device, IAudioClient ** extern HRESULT AudioEndpointVolume_Create(MMDevice *parent, IAudioEndpointVolumeEx **ppv) DECLSPEC_HIDDEN; extern HRESULT AudioSessionManager_Create(IMMDevice *device, IAudioSessionManager2 **ppv) DECLSPEC_HIDDEN; extern HRESULT SpatialAudioClient_Create(IMMDevice *device, ISpatialAudioClient **out) DECLSPEC_HIDDEN; +extern HRESULT DeviceTopology_Create(IMMDevice *device, IDeviceTopology **out) DECLSPEC_HIDDEN;
extern HRESULT load_devices_from_reg(void) DECLSPEC_HIDDEN; extern HRESULT load_driver_devices(EDataFlow flow) DECLSPEC_HIDDEN; diff --git a/dlls/mmdevapi/tests/devicetopology.c b/dlls/mmdevapi/tests/devicetopology.c index 9762bae2d57..e9f576f5007 100644 --- a/dlls/mmdevapi/tests/devicetopology.c +++ b/dlls/mmdevapi/tests/devicetopology.c @@ -84,7 +84,6 @@ START_TEST(devicetopology) if (hr != S_OK || !dev) { if (hr == E_NOINTERFACE) - todo_wine win_skip("IDeviceTopology interface not found\n"); else skip("IDeviceTopology Activation returns 0x%08lx\n", hr);