Commit 10e4eb8a authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

mp3dmod: Support COM aggregation.

parent eeb40543
...@@ -43,7 +43,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(mp3dmod); ...@@ -43,7 +43,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(mp3dmod);
static HINSTANCE mp3dmod_instance; static HINSTANCE mp3dmod_instance;
struct mp3_decoder { struct mp3_decoder {
IUnknown IUnknown_inner;
IMediaObject IMediaObject_iface; IMediaObject IMediaObject_iface;
IUnknown *outer;
LONG ref; LONG ref;
mpg123_handle *mh; mpg123_handle *mh;
DMO_MEDIA_TYPE outtype; DMO_MEDIA_TYPE outtype;
...@@ -51,33 +53,35 @@ struct mp3_decoder { ...@@ -51,33 +53,35 @@ struct mp3_decoder {
REFERENCE_TIME timestamp; REFERENCE_TIME timestamp;
}; };
static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface) static inline struct mp3_decoder *impl_from_IUnknown(IUnknown *iface)
{ {
return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface); return CONTAINING_RECORD(iface, struct mp3_decoder, IUnknown_inner);
} }
static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **ppv) static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
{ {
struct mp3_decoder *This = impl_from_IMediaObject(iface); struct mp3_decoder *This = impl_from_IUnknown(iface);
TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), ppv); TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IMediaObject)) if (IsEqualGUID(iid, &IID_IUnknown))
*ppv = &This->IMediaObject_iface; *obj = &This->IUnknown_inner;
else if (IsEqualGUID(iid, &IID_IMediaObject))
*obj = &This->IMediaObject_iface;
else else
{ {
FIXME("no interface for %s\n", debugstr_guid(iid)); FIXME("no interface for %s\n", debugstr_guid(iid));
*ppv = NULL; *obj = NULL;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
IMediaObject_AddRef(iface); IUnknown_AddRef((IUnknown *)*obj);
return S_OK; return S_OK;
} }
static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface) static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
{ {
struct mp3_decoder *This = impl_from_IMediaObject(iface); struct mp3_decoder *This = impl_from_IUnknown(iface);
ULONG refcount = InterlockedIncrement(&This->ref); ULONG refcount = InterlockedIncrement(&This->ref);
TRACE("(%p) AddRef from %d\n", This, refcount - 1); TRACE("(%p) AddRef from %d\n", This, refcount - 1);
...@@ -85,9 +89,9 @@ static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface) ...@@ -85,9 +89,9 @@ static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
return refcount; return refcount;
} }
static ULONG WINAPI MediaObject_Release(IMediaObject *iface) static ULONG WINAPI Unknown_Release(IUnknown *iface)
{ {
struct mp3_decoder *This = impl_from_IMediaObject(iface); struct mp3_decoder *This = impl_from_IUnknown(iface);
ULONG refcount = InterlockedDecrement(&This->ref); ULONG refcount = InterlockedDecrement(&This->ref);
TRACE("(%p) Release from %d\n", This, refcount + 1); TRACE("(%p) Release from %d\n", This, refcount + 1);
...@@ -100,6 +104,35 @@ static ULONG WINAPI MediaObject_Release(IMediaObject *iface) ...@@ -100,6 +104,35 @@ static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
return refcount; return refcount;
} }
static const IUnknownVtbl Unknown_vtbl = {
Unknown_QueryInterface,
Unknown_AddRef,
Unknown_Release,
};
static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
{
return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface);
}
static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **obj)
{
struct mp3_decoder *This = impl_from_IMediaObject(iface);
return IUnknown_QueryInterface(This->outer, iid, obj);
}
static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
{
struct mp3_decoder *This = impl_from_IMediaObject(iface);
return IUnknown_AddRef(This->outer);
}
static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
{
struct mp3_decoder *This = impl_from_IMediaObject(iface);
return IUnknown_Release(This->outer);
}
static HRESULT WINAPI MediaObject_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output) static HRESULT WINAPI MediaObject_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
{ {
FIXME("(%p)->(%p, %p) stub!\n", iface, input, output); FIXME("(%p)->(%p, %p) stub!\n", iface, input, output);
...@@ -389,7 +422,7 @@ static HRESULT WINAPI MediaObject_Lock(IMediaObject *iface, LONG lock) ...@@ -389,7 +422,7 @@ static HRESULT WINAPI MediaObject_Lock(IMediaObject *iface, LONG lock)
return E_NOTIMPL; return E_NOTIMPL;
} }
static const IMediaObjectVtbl IMediaObject_vtbl = { static const IMediaObjectVtbl MediaObject_vtbl = {
MediaObject_QueryInterface, MediaObject_QueryInterface,
MediaObject_AddRef, MediaObject_AddRef,
MediaObject_Release, MediaObject_Release,
...@@ -416,23 +449,28 @@ static const IMediaObjectVtbl IMediaObject_vtbl = { ...@@ -416,23 +449,28 @@ static const IMediaObjectVtbl IMediaObject_vtbl = {
MediaObject_Lock, MediaObject_Lock,
}; };
static HRESULT create_mp3_decoder(REFIID iid, void **obj) static HRESULT create_mp3_decoder(IUnknown *outer, REFIID iid, void **obj)
{ {
struct mp3_decoder *This; struct mp3_decoder *This;
HRESULT hr;
int err; int err;
if (!(This = heap_alloc_zero(sizeof(*This)))) if (!(This = heap_alloc_zero(sizeof(*This))))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
This->IMediaObject_iface.lpVtbl = &IMediaObject_vtbl; This->IUnknown_inner.lpVtbl = &Unknown_vtbl;
This->ref = 0; This->IMediaObject_iface.lpVtbl = &MediaObject_vtbl;
This->ref = 1;
This->outer = outer ? outer : &This->IUnknown_inner;
mpg123_init(); mpg123_init();
This->mh = mpg123_new(NULL, &err); This->mh = mpg123_new(NULL, &err);
mpg123_open_feed(This->mh); mpg123_open_feed(This->mh);
mpg123_format_none(This->mh); mpg123_format_none(This->mh);
return IMediaObject_QueryInterface(&This->IMediaObject_iface, iid, obj); hr = IUnknown_QueryInterface(&This->IUnknown_inner, iid, obj);
IUnknown_Release(&This->IUnknown_inner);
return hr;
} }
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **obj) static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **obj)
...@@ -466,13 +504,13 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown ...@@ -466,13 +504,13 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown
{ {
TRACE("(%p, %s, %p)\n", outer, debugstr_guid(iid), obj); TRACE("(%p, %s, %p)\n", outer, debugstr_guid(iid), obj);
if (outer) if (outer && !IsEqualGUID(iid, &IID_IUnknown))
{ {
*obj = NULL; *obj = NULL;
return CLASS_E_NOAGGREGATION; return E_NOINTERFACE;
} }
return create_mp3_decoder(iid, obj); return create_mp3_decoder(outer, iid, obj);
} }
static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL lock) static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL lock)
......
...@@ -230,6 +230,62 @@ static void test_convert(void) ...@@ -230,6 +230,62 @@ static void test_convert(void)
IMediaObject_Release(dmo); IMediaObject_Release(dmo);
} }
static const GUID IID_test_outer = {0xdeadbeef,0,0,{0,0,0,0,0,0,0,0x66}};
static HRESULT WINAPI Outer_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
{
if (IsEqualGUID(iid, &IID_test_outer))
{
*obj = (IUnknown *)0xdeadbeef;
return S_OK;
}
ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
return E_NOINTERFACE;
}
static ULONG WINAPI Outer_AddRef(IUnknown *iface)
{
return 2;
}
static ULONG WINAPI Outer_Release(IUnknown *iface)
{
return 1;
}
static IUnknownVtbl Outer_vtbl = {
Outer_QueryInterface,
Outer_AddRef,
Outer_Release,
};
static IUnknown Outer = { &Outer_vtbl };
static void test_aggregation(void)
{
IUnknown *unk, *unk2;
IMediaObject *dmo;
HRESULT hr;
hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
&IID_IUnknown, (void **)&unk);
ok(hr == S_OK, "got %#x\n", hr);
hr = IUnknown_QueryInterface(unk, &IID_IMediaObject, (void **)&dmo);
ok(hr == S_OK, "got %#x\n", hr);
hr = IMediaObject_QueryInterface(dmo, &IID_test_outer, (void **)&unk2);
ok(hr == S_OK, "got %#x\n", hr);
ok(unk2 == (IUnknown *)0xdeadbeef, "got unk %p\n", unk2);
IUnknown_Release(dmo);
IUnknown_Release(unk);
hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
&IID_IMediaObject, (void **)&unk);
ok(hr == E_NOINTERFACE, "got %#x\n", hr);
}
START_TEST(mp3dmod) START_TEST(mp3dmod)
{ {
IMediaObject *dmo; IMediaObject *dmo;
...@@ -247,6 +303,7 @@ START_TEST(mp3dmod) ...@@ -247,6 +303,7 @@ START_TEST(mp3dmod)
IMediaObject_Release(dmo); IMediaObject_Release(dmo);
test_convert(); test_convert();
test_aggregation();
CoUninitialize(); CoUninitialize();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment