diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index e8051eb3baf..2b3fdcd798a 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -63,117 +63,101 @@ static void test_topology(void) hr = IMFTopologyNode_SetTopoNodeID(node2, id); ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr); + hr = IMFTopology_GetNodeCount(topology, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFTopology_AddNode(topology, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + count = 1; hr = IMFTopology_GetNodeCount(topology, &count); -todo_wine { ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); ok(count == 0, "Unexpected node count %u.\n", count); -} + /* Same id, different nodes. */ hr = IMFTopology_AddNode(topology, node); -todo_wine ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr); count = 0; hr = IMFTopology_GetNodeCount(topology, &count); -todo_wine { ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); ok(count == 1, "Unexpected node count %u.\n", count); -} + hr = IMFTopology_AddNode(topology, node2); -todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); IMFTopologyNode_Release(node2); hr = IMFTopology_GetNodeByID(topology, id, &node2); -todo_wine { ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr); ok(node2 == node, "Unexpected node.\n"); -} - if (SUCCEEDED(hr)) - IMFTopologyNode_Release(node2); + IMFTopologyNode_Release(node2); /* Change node id, add it again. */ hr = IMFTopologyNode_SetTopoNodeID(node, ++id); ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr); hr = IMFTopology_GetNodeByID(topology, id, &node2); -todo_wine { ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr); ok(node2 == node, "Unexpected node.\n"); -} - if (SUCCEEDED(hr)) - IMFTopologyNode_Release(node2); + IMFTopologyNode_Release(node2); hr = IMFTopology_GetNodeByID(topology, id + 1, &node2); -todo_wine ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#x.\n", hr); hr = IMFTopology_AddNode(topology, node); -todo_wine ok(hr == E_INVALIDARG, "Failed to add a node, hr %#x.\n", hr); hr = IMFTopology_GetNode(topology, 0, &node2); -todo_wine { ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr); ok(node2 == node, "Unexpected node.\n"); -} - if (SUCCEEDED(hr)) - IMFTopologyNode_Release(node2); + IMFTopologyNode_Release(node2); + + hr = IMFTopology_GetNode(topology, 1, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); hr = IMFTopology_GetNode(topology, 1, &node2); -todo_wine ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#x.\n", hr); hr = IMFTopology_GetNode(topology, -2, &node2); -todo_wine ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#x.\n", hr); hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2); ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr); hr = IMFTopology_AddNode(topology, node2); -todo_wine ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr); IMFTopologyNode_Release(node2); count = 0; hr = IMFTopology_GetNodeCount(topology, &count); -todo_wine { ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); ok(count == 2, "Unexpected node count %u.\n", count); -} + /* Remove with detached node, existing id. */ hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2); ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr); hr = IMFTopologyNode_SetTopoNodeID(node2, id); ok(hr == S_OK, "Failed to set node id, hr %#x.\n", hr); hr = IMFTopology_RemoveNode(topology, node2); -todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); IMFTopologyNode_Release(node2); hr = IMFTopology_RemoveNode(topology, node); -todo_wine ok(hr == S_OK, "Failed to remove a node, hr %#x.\n", hr); count = 0; hr = IMFTopology_GetNodeCount(topology, &count); -todo_wine { ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); ok(count == 1, "Unexpected node count %u.\n", count); -} + hr = IMFTopology_Clear(topology); -todo_wine ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr); count = 1; hr = IMFTopology_GetNodeCount(topology, &count); -todo_wine { ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr); ok(count == 0, "Unexpected node count %u.\n", count); -} + hr = IMFTopology_Clear(topology); -todo_wine ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr); hr = IMFTopologyNode_SetTopoNodeID(node, 123); @@ -189,11 +173,9 @@ todo_wine ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr); hr = IMFTopology_AddNode(topology, node); -todo_wine ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr); hr = IMFTopology_AddNode(topology, node2); -todo_wine ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr); hr = IMFTopologyNode_GetTopoNodeID(node, &id); @@ -203,12 +185,9 @@ todo_wine ok(hr == S_OK, "Failed to get node id, hr %#x.\n", hr); hr = IMFTopology_GetNodeByID(topology, id, &node3); -todo_wine { ok(hr == S_OK, "Failed to get a node, hr %#x.\n", hr); ok(node3 == node, "Unexpected node.\n"); -} - if (SUCCEEDED(hr)) - IMFTopologyNode_Release(node3); + IMFTopologyNode_Release(node3); IMFTopologyNode_Release(node); IMFTopologyNode_Release(node2); diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index 54e9faf94a7..d8012226f49 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -25,6 +25,7 @@ #include "winbase.h" #include "initguid.h" #include "mfapi.h" +#include "mferror.h" #include "mfidl.h" #include "wine/debug.h" @@ -39,6 +40,7 @@ struct topology IMFTopology IMFTopology_iface; LONG refcount; IMFAttributes *attributes; + IMFCollection *nodes; }; struct topology_node @@ -113,7 +115,10 @@ static ULONG WINAPI topology_Release(IMFTopology *iface) if (!refcount) { - IMFAttributes_Release(topology->attributes); + if (topology->attributes) + IMFAttributes_Release(topology->attributes); + if (topology->nodes) + IMFCollection_Release(topology->nodes); heap_free(topology); } @@ -401,39 +406,117 @@ static HRESULT WINAPI topology_GetTopologyID(IMFTopology *iface, TOPOID *id) return E_NOTIMPL; } +static HRESULT topology_get_node_by_id(const struct topology *topology, TOPOID id, IMFTopologyNode **node) +{ + IMFTopologyNode *iter; + unsigned int i = 0; + + while (IMFCollection_GetElement(topology->nodes, i, (IUnknown **)&iter) == S_OK) + { + TOPOID node_id; + HRESULT hr; + + hr = IMFTopologyNode_GetTopoNodeID(iter, &node_id); + if (FAILED(hr)) + return hr; + + if (node_id == id) + { + *node = iter; + return S_OK; + } + + ++i; + } + + return MF_E_NOT_FOUND; +} + static HRESULT WINAPI topology_AddNode(IMFTopology *iface, IMFTopologyNode *node) { - FIXME("(%p)->(%p)\n", iface, node); + struct topology *topology = impl_from_IMFTopology(iface); + IMFTopologyNode *match; + HRESULT hr; + TOPOID id; - return E_NOTIMPL; + TRACE("(%p)->(%p)\n", iface, node); + + if (!node) + return E_POINTER; + + if (FAILED(hr = IMFTopologyNode_GetTopoNodeID(node, &id))) + return hr; + + if (FAILED(topology_get_node_by_id(topology, id, &match))) + return IMFCollection_AddElement(topology->nodes, (IUnknown *)node); + + IMFTopologyNode_Release(match); + + return E_INVALIDARG; } static HRESULT WINAPI topology_RemoveNode(IMFTopology *iface, IMFTopologyNode *node) { - FIXME("(%p)->(%p)\n", iface, node); + struct topology *topology = impl_from_IMFTopology(iface); + unsigned int i = 0; + IUnknown *element; - return E_NOTIMPL; + TRACE("(%p)->(%p)\n", iface, node); + + while (IMFCollection_GetElement(topology->nodes, i, &element) == S_OK) + { + BOOL match = element == (IUnknown *)node; + + IUnknown_Release(element); + + if (match) + { + IMFCollection_RemoveElement(topology->nodes, i, &element); + IUnknown_Release(element); + return S_OK; + } + + ++i; + } + + return E_INVALIDARG; } static HRESULT WINAPI topology_GetNodeCount(IMFTopology *iface, WORD *count) { - FIXME("(%p)->(%p)\n", iface, count); + struct topology *topology = impl_from_IMFTopology(iface); + DWORD nodecount; + HRESULT hr; - return E_NOTIMPL; + TRACE("(%p)->(%p)\n", iface, count); + + hr = IMFCollection_GetElementCount(topology->nodes, count ? &nodecount : NULL); + if (count) + *count = nodecount; + + return hr; } static HRESULT WINAPI topology_GetNode(IMFTopology *iface, WORD index, IMFTopologyNode **node) { - FIXME("(%p)->(%u, %p)\n", iface, index, node); + struct topology *topology = impl_from_IMFTopology(iface); - return E_NOTIMPL; + TRACE("(%p)->(%u, %p)\n", iface, index, node); + + if (!node) + return E_POINTER; + + return SUCCEEDED(IMFCollection_GetElement(topology->nodes, index, (IUnknown **)node)) ? + S_OK : MF_E_INVALIDINDEX; } static HRESULT WINAPI topology_Clear(IMFTopology *iface) { - FIXME("(%p)\n", iface); + struct topology *topology = impl_from_IMFTopology(iface); - return E_NOTIMPL; + TRACE("(%p)\n", iface); + + return IMFCollection_RemoveAllElements(topology->nodes); } static HRESULT WINAPI topology_CloneFrom(IMFTopology *iface, IMFTopology *src_topology) @@ -445,9 +528,11 @@ static HRESULT WINAPI topology_CloneFrom(IMFTopology *iface, IMFTopology *src_to static HRESULT WINAPI topology_GetNodeByID(IMFTopology *iface, TOPOID id, IMFTopologyNode **node) { - FIXME("(%p)->(%p)\n", iface, node); + struct topology *topology = impl_from_IMFTopology(iface); - return E_NOTIMPL; + TRACE("(%p)->(%p)\n", iface, node); + + return topology_get_node_by_id(topology, id, node); } static HRESULT WINAPI topology_GetSourceNodeCollection(IMFTopology *iface, IMFCollection **collection) @@ -530,10 +615,14 @@ HRESULT WINAPI MFCreateTopology(IMFTopology **topology) object->IMFTopology_iface.lpVtbl = &topologyvtbl; object->refcount = 1; + hr = MFCreateAttributes(&object->attributes, 0); + if (SUCCEEDED(hr)) + hr = MFCreateCollection(&object->nodes); + if (FAILED(hr)) { - heap_free(object); + IMFTopology_Release(&object->IMFTopology_iface); return hr; }