/* * Implementation of CLSID_FilterGraph. * * hidenori@a2.ctktv.ne.jp */ #include "config.h" #include "windef.h" #include "winbase.h" #include "wingdi.h" #include "winuser.h" #include "winerror.h" #include "strmif.h" #include "control.h" #include "uuids.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(quartz); #include "quartz_private.h" #include "fgraph.h" /*************************************************************************** * * new/delete for CFilterGraph * */ /* can I use offsetof safely? - FIXME? */ static QUARTZ_IFEntry IFEntries[] = { { &IID_IPersist, offsetof(CFilterGraph,persist)-offsetof(CFilterGraph,unk) }, { &IID_IDispatch, offsetof(CFilterGraph,disp)-offsetof(CFilterGraph,unk) }, { &IID_IFilterGraph, offsetof(CFilterGraph,fgraph)-offsetof(CFilterGraph,unk) }, { &IID_IGraphBuilder, offsetof(CFilterGraph,fgraph)-offsetof(CFilterGraph,unk) }, { &IID_IFilterGraph2, offsetof(CFilterGraph,fgraph)-offsetof(CFilterGraph,unk) }, { &IID_IGraphVersion, offsetof(CFilterGraph,graphversion)-offsetof(CFilterGraph,unk) }, { &IID_IGraphConfig, offsetof(CFilterGraph,grphconf)-offsetof(CFilterGraph,unk) }, { &IID_IMediaControl, offsetof(CFilterGraph,mediacontrol)-offsetof(CFilterGraph,unk) }, { &IID_IMediaFilter, offsetof(CFilterGraph,mediafilter)-offsetof(CFilterGraph,unk) }, { &IID_IMediaEvent, offsetof(CFilterGraph,mediaevent)-offsetof(CFilterGraph,unk) }, { &IID_IMediaEventEx, offsetof(CFilterGraph,mediaevent)-offsetof(CFilterGraph,unk) }, { &IID_IMediaEventSink, offsetof(CFilterGraph,mediaeventsink)-offsetof(CFilterGraph,unk) }, { &IID_IMediaPosition, offsetof(CFilterGraph,mediaposition)-offsetof(CFilterGraph,unk) }, { &IID_IMediaSeeking, offsetof(CFilterGraph,mediaseeking)-offsetof(CFilterGraph,unk) }, { &IID_IBasicVideo, offsetof(CFilterGraph,basvid)-offsetof(CFilterGraph,unk) }, { &IID_IBasicVideo2, offsetof(CFilterGraph,basvid)-offsetof(CFilterGraph,unk) }, { &IID_IBasicAudio, offsetof(CFilterGraph,basaud)-offsetof(CFilterGraph,unk) }, { &IID_IVideoWindow, offsetof(CFilterGraph,vidwin)-offsetof(CFilterGraph,unk) }, }; struct FGInitEntry { HRESULT (*pInit)(CFilterGraph*); void (*pUninit)(CFilterGraph*); }; static const struct FGInitEntry FGRAPH_Init[] = { #define FGENT(a) {&CFilterGraph_Init##a,&CFilterGraph_Uninit##a}, FGENT(IPersist) FGENT(IDispatch) FGENT(IFilterGraph2) FGENT(IGraphVersion) FGENT(IGraphConfig) FGENT(IMediaControl) FGENT(IMediaFilter) FGENT(IMediaEventEx) FGENT(IMediaEventSink) FGENT(IMediaPosition) FGENT(IMediaSeeking) FGENT(IBasicVideo2) FGENT(IBasicAudio) FGENT(IVideoWindow) #undef FGENT { NULL, NULL }, }; static void QUARTZ_DestroyFilterGraph(IUnknown* punk) { CFilterGraph_THIS(punk,unk); int i; TRACE( "(%p)\n", punk ); /* At first, call Stop. */ IMediaControl_Stop( CFilterGraph_IMediaControl(This) ); IMediaFilter_Stop( CFilterGraph_IMediaFilter(This) ); i = 0; while ( FGRAPH_Init[i].pInit != NULL ) { FGRAPH_Init[i].pUninit( This ); i++; } TRACE( "succeeded.\n" ); } HRESULT QUARTZ_CreateFilterGraph(IUnknown* punkOuter,void** ppobj) { CFilterGraph* pfg; HRESULT hr; int i; TRACE("(%p,%p)\n",punkOuter,ppobj); pfg = (CFilterGraph*)QUARTZ_AllocObj( sizeof(CFilterGraph) ); if ( pfg == NULL ) return E_OUTOFMEMORY; QUARTZ_IUnkInit( &pfg->unk, punkOuter ); i = 0; hr = NOERROR; while ( FGRAPH_Init[i].pInit != NULL ) { hr = FGRAPH_Init[i].pInit( pfg ); if ( FAILED(hr) ) break; i++; } if ( FAILED(hr) ) { while ( --i >= 0 ) FGRAPH_Init[i].pUninit( pfg ); QUARTZ_FreeObj( pfg ); return hr; } pfg->unk.pEntries = IFEntries; pfg->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]); pfg->unk.pOnFinalRelease = QUARTZ_DestroyFilterGraph; *ppobj = (void*)(&pfg->unk); return S_OK; } /*************************************************************************** * * CFilterGraph::IPersist * */ static HRESULT WINAPI IPersist_fnQueryInterface(IPersist* iface,REFIID riid,void** ppobj) { CFilterGraph_THIS(iface,persist); TRACE("(%p)->()\n",This); return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj); } static ULONG WINAPI IPersist_fnAddRef(IPersist* iface) { CFilterGraph_THIS(iface,persist); TRACE("(%p)->()\n",This); return IUnknown_AddRef(This->unk.punkControl); } static ULONG WINAPI IPersist_fnRelease(IPersist* iface) { CFilterGraph_THIS(iface,persist); TRACE("(%p)->()\n",This); return IUnknown_Release(This->unk.punkControl); } static HRESULT WINAPI IPersist_fnGetClassID(IPersist* iface,CLSID* pclsid) { CFilterGraph_THIS(iface,persist); TRACE("(%p)->()\n",This); if ( pclsid == NULL ) return E_POINTER; memcpy( pclsid, &CLSID_FilterGraph, sizeof(CLSID) ); return E_NOTIMPL; } static ICOM_VTABLE(IPersist) ipersist = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE /* IUnknown fields */ IPersist_fnQueryInterface, IPersist_fnAddRef, IPersist_fnRelease, /* IPersist fields */ IPersist_fnGetClassID, }; HRESULT CFilterGraph_InitIPersist( CFilterGraph* pfg ) { TRACE("(%p)\n",pfg); ICOM_VTBL(&pfg->persist) = &ipersist; return NOERROR; } void CFilterGraph_UninitIPersist( CFilterGraph* pfg ) { TRACE("(%p)\n",pfg); } /*************************************************************************** * * CFilterGraph::IDispatch * */ static HRESULT WINAPI IDispatch_fnQueryInterface(IDispatch* iface,REFIID riid,void** ppobj) { CFilterGraph_THIS(iface,disp); TRACE("(%p)->()\n",This); return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj); } static ULONG WINAPI IDispatch_fnAddRef(IDispatch* iface) { CFilterGraph_THIS(iface,disp); TRACE("(%p)->()\n",This); return IUnknown_AddRef(This->unk.punkControl); } static ULONG WINAPI IDispatch_fnRelease(IDispatch* iface) { CFilterGraph_THIS(iface,disp); TRACE("(%p)->()\n",This); return IUnknown_Release(This->unk.punkControl); } static HRESULT WINAPI IDispatch_fnGetTypeInfoCount(IDispatch* iface,UINT* pcTypeInfo) { CFilterGraph_THIS(iface,disp); FIXME("(%p)->()\n",This); return E_NOTIMPL; } static HRESULT WINAPI IDispatch_fnGetTypeInfo(IDispatch* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj) { CFilterGraph_THIS(iface,disp); FIXME("(%p)->()\n",This); return E_NOTIMPL; } static HRESULT WINAPI IDispatch_fnGetIDsOfNames(IDispatch* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId) { CFilterGraph_THIS(iface,disp); FIXME("(%p)->()\n",This); return E_NOTIMPL; } static HRESULT WINAPI IDispatch_fnInvoke(IDispatch* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr) { CFilterGraph_THIS(iface,disp); FIXME("(%p)->()\n",This); return E_NOTIMPL; } static ICOM_VTABLE(IDispatch) idispatch = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE /* IUnknown fields */ IDispatch_fnQueryInterface, IDispatch_fnAddRef, IDispatch_fnRelease, /* IDispatch fields */ IDispatch_fnGetTypeInfoCount, IDispatch_fnGetTypeInfo, IDispatch_fnGetIDsOfNames, IDispatch_fnInvoke, }; HRESULT CFilterGraph_InitIDispatch( CFilterGraph* pfg ) { TRACE("(%p)\n",pfg); ICOM_VTBL(&pfg->disp) = &idispatch; return NOERROR; } void CFilterGraph_UninitIDispatch( CFilterGraph* pfg ) { TRACE("(%p)\n",pfg); }