From f423c6e7079f797f81fe2f32db089eed5320b4d4 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 17 May 2019 00:31:05 -0500 Subject: [PATCH] amstream: Reimplement IMediaStreamFilter::EnumPins(). Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/amstream/amstream_private.h | 1 + dlls/amstream/mediastreamfilter.c | 167 +++++++++++++++++++++++++++++- dlls/amstream/tests/amstream.c | 16 +-- 3 files changed, 174 insertions(+), 10 deletions(-) diff --git a/dlls/amstream/amstream_private.h b/dlls/amstream/amstream_private.h index 8f25b8e248e..3cbc5c8e64b 100644 --- a/dlls/amstream/amstream_private.h +++ b/dlls/amstream/amstream_private.h @@ -32,6 +32,7 @@ #include "mmstream.h" #include "austream.h" #include "amstream.h" +#include "wine/heap.h" HRESULT AM_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN; HRESULT AMAudioData_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN; diff --git a/dlls/amstream/mediastreamfilter.c b/dlls/amstream/mediastreamfilter.c index a61d1e767c0..e9f98b63ca7 100644 --- a/dlls/amstream/mediastreamfilter.c +++ b/dlls/amstream/mediastreamfilter.c @@ -34,6 +34,142 @@ WINE_DEFAULT_DEBUG_CHANNEL(amstream); +struct enum_pins +{ + IEnumPins IEnumPins_iface; + LONG refcount; + + IPin **pins; + unsigned int count, index; +}; + +static const IEnumPinsVtbl enum_pins_vtbl; + +static struct enum_pins *impl_from_IEnumPins(IEnumPins *iface) +{ + return CONTAINING_RECORD(iface, struct enum_pins, IEnumPins_iface); +} + +static HRESULT WINAPI enum_pins_QueryInterface(IEnumPins *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumPins)) + { + IEnumPins_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI enum_pins_AddRef(IEnumPins *iface) +{ + struct enum_pins *enum_pins = impl_from_IEnumPins(iface); + ULONG refcount = InterlockedIncrement(&enum_pins->refcount); + TRACE("%p increasing refcount to %u.\n", enum_pins, refcount); + return refcount; +} + +static ULONG WINAPI enum_pins_Release(IEnumPins *iface) +{ + struct enum_pins *enum_pins = impl_from_IEnumPins(iface); + ULONG refcount = InterlockedDecrement(&enum_pins->refcount); + unsigned int i; + + TRACE("%p decreasing refcount to %u.\n", enum_pins, refcount); + if (!refcount) + { + for (i = 0; i < enum_pins->count; ++i) + IPin_Release(enum_pins->pins[i]); + heap_free(enum_pins->pins); + heap_free(enum_pins); + } + return refcount; +} + +static HRESULT WINAPI enum_pins_Next(IEnumPins *iface, ULONG count, IPin **pins, ULONG *ret_count) +{ + struct enum_pins *enum_pins = impl_from_IEnumPins(iface); + unsigned int i; + + TRACE("iface %p, count %u, pins %p, ret_count %p.\n", iface, count, pins, ret_count); + + if (!pins || (count > 1 && !ret_count)) + return E_POINTER; + + for (i = 0; i < count && enum_pins->index < enum_pins->count; ++i) + { + IPin_AddRef(pins[i] = enum_pins->pins[i]); + enum_pins->index++; + } + + if (ret_count) *ret_count = i; + return i == count ? S_OK : S_FALSE; +} + +static HRESULT WINAPI enum_pins_Skip(IEnumPins *iface, ULONG count) +{ + struct enum_pins *enum_pins = impl_from_IEnumPins(iface); + + TRACE("iface %p, count %u.\n", iface, count); + + enum_pins->index += count; + + return enum_pins->index >= enum_pins->count ? S_FALSE : S_OK; +} + +static HRESULT WINAPI enum_pins_Reset(IEnumPins *iface) +{ + struct enum_pins *enum_pins = impl_from_IEnumPins(iface); + + TRACE("iface %p.\n", iface); + + enum_pins->index = 0; + return S_OK; +} + +static HRESULT WINAPI enum_pins_Clone(IEnumPins *iface, IEnumPins **out) +{ + struct enum_pins *enum_pins = impl_from_IEnumPins(iface); + struct enum_pins *object; + unsigned int i; + + TRACE("iface %p, out %p.\n", iface, out); + + if (!(object = heap_alloc(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IEnumPins_iface.lpVtbl = &enum_pins_vtbl; + object->refcount = 1; + object->count = enum_pins->count; + object->index = enum_pins->index; + if (!(object->pins = heap_alloc(enum_pins->count * sizeof(*object->pins)))) + { + heap_free(object); + return E_OUTOFMEMORY; + } + for (i = 0; i < enum_pins->count; ++i) + IPin_AddRef(object->pins[i] = enum_pins->pins[i]); + + *out = &object->IEnumPins_iface; + return S_OK; +} + +static const IEnumPinsVtbl enum_pins_vtbl = +{ + enum_pins_QueryInterface, + enum_pins_AddRef, + enum_pins_Release, + enum_pins_Next, + enum_pins_Skip, + enum_pins_Reset, + enum_pins_Clone, +}; + typedef struct { BaseFilter filter; ULONG nb_streams; @@ -153,8 +289,35 @@ static HRESULT WINAPI MediaStreamFilterImpl_GetSyncSource(IMediaStreamFilter *if static HRESULT WINAPI MediaStreamFilterImpl_EnumPins(IMediaStreamFilter *iface, IEnumPins **enum_pins) { - IMediaStreamFilterImpl *This = impl_from_IMediaStreamFilter(iface); - return BaseFilterImpl_EnumPins(&This->filter.IBaseFilter_iface, enum_pins); + IMediaStreamFilterImpl *filter = impl_from_IMediaStreamFilter(iface); + struct enum_pins *object; + unsigned int i; + + TRACE("iface %p, enum_pins %p.\n", iface, enum_pins); + + if (!enum_pins) + return E_POINTER; + + if (!(object = heap_alloc(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->IEnumPins_iface.lpVtbl = &enum_pins_vtbl; + object->refcount = 1; + object->count = filter->nb_streams; + object->index = 0; + if (!(object->pins = heap_alloc(filter->nb_streams * sizeof(*object->pins)))) + { + heap_free(object); + return E_OUTOFMEMORY; + } + for (i = 0; i < filter->nb_streams; ++i) + { + if (FAILED(IAMMediaStream_QueryInterface(filter->streams[i], &IID_IPin, (void **)&object->pins[i]))) + WARN("Stream %p does not support IPin.\n", filter->streams[i]); + } + + *enum_pins = &object->IEnumPins_iface; + return S_OK; } static HRESULT WINAPI MediaStreamFilterImpl_FindPin(IMediaStreamFilter *iface, LPCWSTR id, IPin **pin) diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 148e6bdc78f..72157755d1c 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -652,7 +652,7 @@ static void test_enum_pins(void) hr = IMediaStreamFilter_EnumPins(filter, &enum1); ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(filter); - todo_wine ok(ref == 3, "Got unexpected refcount %d.\n", ref); + ok(ref == 3, "Got unexpected refcount %d.\n", ref); ref = get_refcount(enum1); ok(ref == 1, "Got unexpected refcount %d.\n", ref); @@ -666,7 +666,7 @@ static void test_enum_pins(void) ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IEnumPins_Skip(enum1, 0); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); hr = IEnumPins_Skip(enum1, 1); ok(hr == S_FALSE, "Got hr %#x.\n", hr); @@ -682,7 +682,7 @@ static void test_enum_pins(void) ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IEnumPins_Next(enum1, 1, pins, NULL); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); IEnumPins_Release(enum1); @@ -690,7 +690,7 @@ static void test_enum_pins(void) ok(hr == S_OK, "Got hr %#x.\n", hr); ref = get_refcount(filter); - ok(ref == 4, "Got unexpected refcount %d.\n", ref); + todo_wine ok(ref == 4, "Got unexpected refcount %d.\n", ref); ref = get_refcount(enum1); ok(ref == 1, "Got unexpected refcount %d.\n", ref); ref = get_refcount(pin); @@ -700,7 +700,7 @@ static void test_enum_pins(void) ok(hr == S_OK, "Got hr %#x.\n", hr); ok(pins[0] == pin, "Expected pin %p, got %p.\n", pin, pins[0]); ref = get_refcount(filter); - ok(ref == 4, "Got unexpected refcount %d.\n", ref); + todo_wine ok(ref == 4, "Got unexpected refcount %d.\n", ref); ref = get_refcount(enum1); ok(ref == 1, "Got unexpected refcount %d.\n", ref); ref = get_refcount(pin); @@ -723,7 +723,7 @@ static void test_enum_pins(void) ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IEnumPins_Next(enum1, 2, pins, NULL); - todo_wine ok(hr == E_POINTER, "Got hr %#x.\n", hr); + ok(hr == E_POINTER, "Got hr %#x.\n", hr); hr = IEnumPins_Next(enum1, 2, pins, &count); ok(hr == S_FALSE, "Got hr %#x.\n", hr); @@ -741,7 +741,7 @@ static void test_enum_pins(void) ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IEnumPins_Skip(enum1, 1); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); hr = IEnumPins_Next(enum1, 1, pins, NULL); ok(hr == S_FALSE, "Got hr %#x.\n", hr); @@ -759,7 +759,7 @@ static void test_enum_pins(void) ok(!ref, "Got outstanding refcount %d.\n", ref); IMediaStream_Release(stream); ref = IPin_Release(pin); - todo_wine ok(!ref, "Got outstanding refcount %d.\n", ref); + ok(!ref, "Got outstanding refcount %d.\n", ref); } static void test_find_pin(void)