/* * Implementation of CLSID_FilterGraph. * * hidenori@a2.ctktv.ne.jp */ #include "config.h" #include "windef.h" #include "winbase.h" #include "wingdi.h" #include "winerror.h" #include "wine/obj_base.h" #include "wine/obj_oleaut.h" #include "strmif.h" #include "control.h" #include "uuids.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(quartz); #include "quartz_private.h" #include "fgraph.h" /* 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_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(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; /* 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; }