[PATCH 4/4] qedit: Support COM aggregation for SampleGrabber.
Michael Stefaniuc
mstefani at redhat.de
Tue Jun 26 16:54:49 CDT 2012
---
dlls/qedit/main.c | 3 +
dlls/qedit/samplegrabber.c | 137 ++++++++++++++++++++++++------------------
dlls/qedit/tests/mediadet.c | 3 +-
3 files changed, 82 insertions(+), 61 deletions(-)
diff --git a/dlls/qedit/main.c b/dlls/qedit/main.c
index 734f326..6b0375e 100644
--- a/dlls/qedit/main.c
+++ b/dlls/qedit/main.c
@@ -105,6 +105,9 @@ static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
*ppobj = NULL;
+ if (pOuter && !IsEqualGUID(&IID_IUnknown, riid))
+ return E_INVALIDARG;
+
hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
if (SUCCEEDED(hres)) {
hres = IUnknown_QueryInterface(punk, riid, ppobj);
diff --git a/dlls/qedit/samplegrabber.c b/dlls/qedit/samplegrabber.c
index 6080b6e..c748c98 100644
--- a/dlls/qedit/samplegrabber.c
+++ b/dlls/qedit/samplegrabber.c
@@ -365,11 +365,13 @@ static inline SG_Pin *impl_from_IPin(IPin *iface)
/* Sample Grabber filter implementation */
typedef struct _SG_Impl {
+ IUnknown IUnknown_inner;
IBaseFilter IBaseFilter_iface;
ISampleGrabber ISampleGrabber_iface;
IMemInputPin IMemInputPin_iface;
/* TODO: IMediaPosition, IMediaSeeking, IQualityControl */
- LONG refCount;
+ IUnknown *outer_unk;
+ LONG ref;
CRITICAL_SECTION critSect;
FILTER_INFO info;
FILTER_STATE state;
@@ -392,7 +394,11 @@ enum {
OneShot_Past,
};
-/* Get the SampleGrabber implementation This pointer from various interface pointers */
+static inline SG_Impl *impl_from_IUnknown(IUnknown *iface)
+{
+ return CONTAINING_RECORD(iface, SG_Impl, IUnknown_inner);
+}
+
static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
{
return CONTAINING_RECORD(iface, SG_Impl, IBaseFilter_iface);
@@ -431,61 +437,71 @@ static void SampleGrabber_cleanup(SG_Impl *This)
DeleteCriticalSection(&This->critSect);
}
-/* Common helper AddRef called from all interfaces */
-static ULONG SampleGrabber_addref(SG_Impl *This)
+/* SampleGrabber inner IUnknown */
+static HRESULT WINAPI SampleGrabber_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
- ULONG refCount = InterlockedIncrement(&This->refCount);
- TRACE("(%p) new ref = %u\n", This, refCount);
- return refCount;
+ SG_Impl *This = impl_from_IUnknown(iface);
+
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+
+ *ppv = NULL;
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = &This->IUnknown_inner;
+ else if (IsEqualIID(riid, &IID_IPersist) || IsEqualIID(riid, &IID_IMediaFilter) ||
+ IsEqualIID(riid, &IID_IBaseFilter))
+ *ppv = &This->IBaseFilter_iface;
+ else if (IsEqualIID(riid, &IID_ISampleGrabber))
+ *ppv = &This->ISampleGrabber_iface;
+ else if (IsEqualIID(riid, &IID_IMemInputPin))
+ *ppv = &This->IMemInputPin_iface;
+ else if (IsEqualIID(riid, &IID_IMediaPosition))
+ FIXME("IMediaPosition not implemented\n");
+ else if (IsEqualIID(riid, &IID_IMediaSeeking))
+ FIXME("IMediaSeeking not implemented\n");
+ else if (IsEqualIID(riid, &IID_IQualityControl))
+ FIXME("IQualityControl not implemented\n");
+ else
+ WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppv);
+
+ if (!*ppv)
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
}
-/* Common helper Release called from all interfaces */
-static ULONG SampleGrabber_release(SG_Impl *This)
+static ULONG WINAPI SampleGrabber_AddRef(IUnknown *iface)
{
- ULONG refCount = InterlockedDecrement(&This->refCount);
- TRACE("(%p) new ref = %u\n", This, refCount);
- if (refCount == 0)
+ SG_Impl *This = impl_from_IUnknown(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) new ref = %u\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI SampleGrabber_Release(IUnknown *iface)
+{
+ SG_Impl *This = impl_from_IUnknown(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) new ref = %u\n", This, ref);
+
+ if (ref == 0)
{
SampleGrabber_cleanup(This);
CoTaskMemFree(This);
return 0;
}
- return refCount;
+ return ref;
}
-/* Common helper QueryInterface called from all interfaces */
-static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject)
+static const IUnknownVtbl samplegrabber_vtbl =
{
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
-
- if (IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IPersist) ||
- IsEqualIID(riid, &IID_IMediaFilter) ||
- IsEqualIID(riid, &IID_IBaseFilter)) {
- SampleGrabber_addref(This);
- *ppvObject = &This->IBaseFilter_iface;
- return S_OK;
- }
- else if (IsEqualIID(riid, &IID_ISampleGrabber)) {
- SampleGrabber_addref(This);
- *ppvObject = &This->ISampleGrabber_iface;
- return S_OK;
- }
- else if (IsEqualIID(riid, &IID_IMemInputPin)) {
- SampleGrabber_addref(This);
- *ppvObject = &This->IMemInputPin_iface;
- return S_OK;
- }
- else if (IsEqualIID(riid, &IID_IMediaPosition))
- FIXME("IMediaPosition not implemented\n");
- else if (IsEqualIID(riid, &IID_IMediaSeeking))
- FIXME("IMediaSeeking not implemented\n");
- else if (IsEqualIID(riid, &IID_IQualityControl))
- FIXME("IQualityControl not implemented\n");
- *ppvObject = NULL;
- WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
- return E_NOINTERFACE;
-}
+ SampleGrabber_QueryInterface,
+ SampleGrabber_AddRef,
+ SampleGrabber_Release,
+};
/* Helper that buffers data and/or calls installed sample callbacks */
static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
@@ -554,7 +570,7 @@ static HRESULT WINAPI
SampleGrabber_IBaseFilter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppv)
{
SG_Impl *This = impl_from_IBaseFilter(iface);
- return SampleGrabber_query(This, riid, ppv);
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
/* IUnknown */
@@ -562,7 +578,7 @@ static ULONG WINAPI
SampleGrabber_IBaseFilter_AddRef(IBaseFilter *iface)
{
SG_Impl *This = impl_from_IBaseFilter(iface);
- return SampleGrabber_addref(This);
+ return IUnknown_AddRef(This->outer_unk);
}
/* IUnknown */
@@ -570,7 +586,7 @@ static ULONG WINAPI
SampleGrabber_IBaseFilter_Release(IBaseFilter *iface)
{
SG_Impl *This = impl_from_IBaseFilter(iface);
- return SampleGrabber_release(This);
+ return IUnknown_Release(This->outer_unk);
}
/* IPersist */
@@ -743,7 +759,7 @@ static HRESULT WINAPI
SampleGrabber_ISampleGrabber_QueryInterface(ISampleGrabber *iface, REFIID riid, void **ppv)
{
SG_Impl *This = impl_from_ISampleGrabber(iface);
- return SampleGrabber_query(This, riid, ppv);
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
/* IUnknown */
@@ -751,7 +767,7 @@ static ULONG WINAPI
SampleGrabber_ISampleGrabber_AddRef(ISampleGrabber *iface)
{
SG_Impl *This = impl_from_ISampleGrabber(iface);
- return SampleGrabber_addref(This);
+ return IUnknown_AddRef(This->outer_unk);
}
/* IUnknown */
@@ -759,7 +775,7 @@ static ULONG WINAPI
SampleGrabber_ISampleGrabber_Release(ISampleGrabber *iface)
{
SG_Impl *This = impl_from_ISampleGrabber(iface);
- return SampleGrabber_release(This);
+ return IUnknown_Release(This->outer_unk);
}
/* ISampleGrabber */
@@ -893,7 +909,7 @@ static HRESULT WINAPI
SampleGrabber_IMemInputPin_QueryInterface(IMemInputPin *iface, REFIID riid, void **ppv)
{
SG_Impl *This = impl_from_IMemInputPin(iface);
- return SampleGrabber_query(This, riid, ppv);
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
/* IUnknown */
@@ -901,7 +917,7 @@ static ULONG WINAPI
SampleGrabber_IMemInputPin_AddRef(IMemInputPin *iface)
{
SG_Impl *This = impl_from_IMemInputPin(iface);
- return SampleGrabber_addref(This);
+ return IUnknown_AddRef(This->outer_unk);
}
/* IUnknown */
@@ -909,7 +925,7 @@ static ULONG WINAPI
SampleGrabber_IMemInputPin_Release(IMemInputPin *iface)
{
SG_Impl *This = impl_from_IMemInputPin(iface);
- return SampleGrabber_release(This);
+ return IUnknown_Release(This->outer_unk);
}
/* IMemInputPin */
@@ -1454,9 +1470,6 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
TRACE("(%p,%p)\n", ppv, pUnkOuter);
- if (pUnkOuter)
- return CLASS_E_NOAGGREGATION;
-
obj = CoTaskMemAlloc(sizeof(SG_Impl));
if (NULL == obj) {
*ppv = NULL;
@@ -1464,7 +1477,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
}
ZeroMemory(obj, sizeof(SG_Impl));
- obj->refCount = 1;
+ obj->ref = 1;
+ obj->IUnknown_inner.lpVtbl = &samplegrabber_vtbl;
obj->IBaseFilter_iface.lpVtbl = &IBaseFilter_VTable;
obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable;
obj->IMemInputPin_iface.lpVtbl = &IMemInputPin_VTable;
@@ -1494,7 +1508,12 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
obj->oneShot = OneShot_None;
obj->bufferLen = -1;
obj->bufferData = NULL;
- *ppv = obj;
+ if (pUnkOuter)
+ obj->outer_unk = pUnkOuter;
+ else
+ obj->outer_unk = &obj->IUnknown_inner;
+
+ *ppv = &obj->IUnknown_inner;
return S_OK;
}
diff --git a/dlls/qedit/tests/mediadet.c b/dlls/qedit/tests/mediadet.c
index 1d75680..1229db6 100644
--- a/dlls/qedit/tests/mediadet.c
+++ b/dlls/qedit/tests/mediadet.c
@@ -353,8 +353,7 @@ static void test_samplegrabber(void)
/* COM aggregation */
hr = CoCreateInstance(&CLSID_SampleGrabber, &unk_obj.IUnknown_iface, CLSCTX_INPROC_SERVER,
&IID_IUnknown, (void**)&unk_obj.inner_unk);
- todo_wine ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
- if (hr != S_OK) return;
+ ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
hr = IUnknown_QueryInterface(unk_obj.inner_unk, &IID_ISampleGrabber, (void**)&sg);
ok(hr == S_OK, "QueryInterface for IID_ISampleGrabber failed: %08x\n", hr);
--
1.7.6.5
More information about the wine-patches
mailing list