mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 10:47:18 +00:00
mp3dmod: Support COM aggregation.
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
eeb40543cb
commit
10e4eb8aca
|
@ -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 {
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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 = {
|
||||||
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
|
||||||
{
|
{
|
||||||
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)
|
||||||
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)
|
||||||
IMediaObject_Release(dmo);
|
IMediaObject_Release(dmo);
|
||||||
|
|
||||||
test_convert();
|
test_convert();
|
||||||
|
test_aggregation();
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue