2 * Implementation of IMediaFilter for FilterGraph.
6 * hidenori@a2.ctktv.ne.jp
16 #include "wine/obj_base.h"
17 #include "wine/obj_oleaut.h"
24 #include "debugtools.h"
25 DEFAULT_DEBUG_CHANNEL(quartz
);
27 #include "quartz_private.h"
31 #define WINE_QUARTZ_POLL_INTERVAL 10
33 /*****************************************************************************/
36 HRESULT
CFilterGraph_PollGraphState(
41 QUARTZ_CompListItem
* pItem
;
46 EnterCriticalSection( &This
->m_csGraphState
);
47 QUARTZ_CompList_Lock( This
->m_pFilterList
);
49 pItem
= QUARTZ_CompList_GetFirst( This
->m_pFilterList
);
51 while ( pItem
!= NULL
)
53 pFilter
= (IBaseFilter
*)QUARTZ_CompList_GetItemPtr( pItem
);
54 hr
= IBaseFilter_GetState( pFilter
, (DWORD
)0, pState
);
58 pItem
= QUARTZ_CompList_GetNext( This
->m_pFilterList
, pItem
);
61 QUARTZ_CompList_Unlock( This
->m_pFilterList
);
62 LeaveCriticalSection( &This
->m_csGraphState
);
64 TRACE( "returns %08lx, state %d\n",
70 /*****************************************************************************/
73 IMediaFilter_fnQueryInterface(IMediaFilter
* iface
,REFIID riid
,void** ppobj
)
75 CFilterGraph_THIS(iface
,mediafilter
);
77 TRACE("(%p)->()\n",This
);
79 return IUnknown_QueryInterface(This
->unk
.punkControl
,riid
,ppobj
);
83 IMediaFilter_fnAddRef(IMediaFilter
* iface
)
85 CFilterGraph_THIS(iface
,mediafilter
);
87 TRACE("(%p)->()\n",This
);
89 return IUnknown_AddRef(This
->unk
.punkControl
);
93 IMediaFilter_fnRelease(IMediaFilter
* iface
)
95 CFilterGraph_THIS(iface
,mediafilter
);
97 TRACE("(%p)->()\n",This
);
99 return IUnknown_Release(This
->unk
.punkControl
);
103 static HRESULT WINAPI
104 IMediaFilter_fnGetClassID(IMediaFilter
* iface
,CLSID
* pclsid
)
106 CFilterGraph_THIS(iface
,mediafilter
);
108 TRACE("(%p)->()\n",This
);
110 return IPersist_GetClassID(
111 CFilterGraph_IPersist(This
),pclsid
);
114 static HRESULT WINAPI
115 IMediaFilter_fnStop(IMediaFilter
* iface
)
117 CFilterGraph_THIS(iface
,mediafilter
);
120 QUARTZ_CompListItem
* pItem
;
121 IBaseFilter
* pFilter
;
123 TRACE("(%p)->()\n",This
);
127 EnterCriticalSection( &This
->m_csGraphState
);
129 if ( This
->m_stateGraph
!= State_Stopped
)
131 /* IDistributorNotify_Stop() */
133 QUARTZ_CompList_Lock( This
->m_pFilterList
);
135 pItem
= QUARTZ_CompList_GetFirst( This
->m_pFilterList
);
137 while ( pItem
!= NULL
)
139 pFilter
= (IBaseFilter
*)QUARTZ_CompList_GetItemPtr( pItem
);
140 hrFilter
= IBaseFilter_Stop( pFilter
);
141 if ( hrFilter
!= S_OK
)
147 pItem
= QUARTZ_CompList_GetNext( This
->m_pFilterList
, pItem
);
150 QUARTZ_CompList_Unlock( This
->m_pFilterList
);
152 This
->m_stateGraph
= State_Stopped
;
155 LeaveCriticalSection( &This
->m_csGraphState
);
160 static HRESULT WINAPI
161 IMediaFilter_fnPause(IMediaFilter
* iface
)
163 CFilterGraph_THIS(iface
,mediafilter
);
166 QUARTZ_CompListItem
* pItem
;
167 IBaseFilter
* pFilter
;
169 TRACE("(%p)->()\n",This
);
173 EnterCriticalSection( &This
->m_csGraphState
);
175 if ( This
->m_stateGraph
!= State_Paused
)
177 /* IDistributorNotify_Pause() */
179 QUARTZ_CompList_Lock( This
->m_pFilterList
);
181 pItem
= QUARTZ_CompList_GetFirst( This
->m_pFilterList
);
183 while ( pItem
!= NULL
)
185 pFilter
= (IBaseFilter
*)QUARTZ_CompList_GetItemPtr( pItem
);
186 hrFilter
= IBaseFilter_Pause( pFilter
);
187 if ( hrFilter
!= S_OK
)
193 pItem
= QUARTZ_CompList_GetNext( This
->m_pFilterList
, pItem
);
196 QUARTZ_CompList_Unlock( This
->m_pFilterList
);
198 This
->m_stateGraph
= State_Paused
;
201 LeaveCriticalSection( &This
->m_csGraphState
);
206 static HRESULT WINAPI
207 IMediaFilter_fnRun(IMediaFilter
* iface
,REFERENCE_TIME rtStart
)
209 CFilterGraph_THIS(iface
,mediafilter
);
212 QUARTZ_CompListItem
* pItem
;
213 IBaseFilter
* pFilter
;
214 IReferenceClock
* pClock
;
216 TRACE("(%p)->()\n",This
);
218 EnterCriticalSection( &This
->m_csGraphState
);
220 if ( This
->m_stateGraph
== State_Stopped
)
222 hr
= IMediaFilter_Pause(iface
);
227 /* handle the special time. */
228 if ( rtStart
== (REFERENCE_TIME
)0 )
230 hr
= IMediaFilter_GetSyncSource(iface
,&pClock
);
231 if ( hr
== S_OK
&& pClock
!= NULL
)
233 IReferenceClock_GetTime(pClock
,&rtStart
);
234 IReferenceClock_Release(pClock
);
240 if ( This
->m_stateGraph
!= State_Running
)
242 /* IDistributorNotify_Run() */
244 QUARTZ_CompList_Lock( This
->m_pFilterList
);
246 pItem
= QUARTZ_CompList_GetFirst( This
->m_pFilterList
);
248 while ( pItem
!= NULL
)
250 pFilter
= (IBaseFilter
*)QUARTZ_CompList_GetItemPtr( pItem
);
251 hrFilter
= IBaseFilter_Run( pFilter
, rtStart
);
252 if ( hrFilter
!= S_OK
)
258 pItem
= QUARTZ_CompList_GetNext( This
->m_pFilterList
, pItem
);
261 QUARTZ_CompList_Unlock( This
->m_pFilterList
);
263 This
->m_stateGraph
= State_Running
;
267 LeaveCriticalSection( &This
->m_csGraphState
);
272 static HRESULT WINAPI
273 IMediaFilter_fnGetState(IMediaFilter
* iface
,DWORD dwTimeOut
,FILTER_STATE
* pState
)
275 CFilterGraph_THIS(iface
,mediafilter
);
280 TRACE("(%p)->(%p)\n",This
,pState
);
281 if ( pState
== NULL
)
284 dwTickStart
= GetTickCount();
288 hr
= CFilterGraph_PollGraphState( This
, pState
);
289 if ( hr
!= VFW_S_STATE_INTERMEDIATE
)
291 if ( dwTimeOut
== 0 )
294 Sleep( (dwTimeOut
>= WINE_QUARTZ_POLL_INTERVAL
) ?
295 WINE_QUARTZ_POLL_INTERVAL
: dwTimeOut
);
297 dwTickUsed
= GetTickCount() - dwTickStart
;
299 dwTickStart
+= dwTickUsed
;
300 if ( dwTimeOut
<= dwTickUsed
)
303 dwTimeOut
-= dwTickUsed
;
306 EnterCriticalSection( &This
->m_csGraphState
);
307 *pState
= This
->m_stateGraph
;
308 LeaveCriticalSection( &This
->m_csGraphState
);
313 static HRESULT WINAPI
314 IMediaFilter_fnSetSyncSource(IMediaFilter
* iface
,IReferenceClock
* pobjClock
)
316 CFilterGraph_THIS(iface
,mediafilter
);
317 QUARTZ_CompListItem
* pItem
;
318 IBaseFilter
* pFilter
;
319 HRESULT hr
= NOERROR
;
322 TRACE("(%p)->(%p)\n",This
,pobjClock
);
324 /* IDistributorNotify_SetSyncSource() */
326 EnterCriticalSection( &This
->m_csClock
);
327 QUARTZ_CompList_Lock( This
->m_pFilterList
);
329 if ( This
->m_pClock
!= NULL
)
331 IReferenceClock_Release(This
->m_pClock
);
332 This
->m_pClock
= NULL
;
335 This
->m_pClock
= pobjClock
;
336 if ( pobjClock
!= NULL
)
337 IReferenceClock_AddRef( pobjClock
);
339 pItem
= QUARTZ_CompList_GetFirst( This
->m_pFilterList
);
340 while ( pItem
!= NULL
)
342 pFilter
= (IBaseFilter
*)QUARTZ_CompList_GetItemPtr( pItem
);
343 hrCur
= IBaseFilter_SetSyncSource(pFilter
,pobjClock
);
346 pItem
= QUARTZ_CompList_GetNext( This
->m_pFilterList
, pItem
);
349 QUARTZ_CompList_Unlock( This
->m_pFilterList
);
351 if ( This
->m_pClock
!= NULL
)
352 IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This
),
353 EC_CLOCK_CHANGED
, 0, 0);
355 IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This
),
356 EC_CLOCK_UNSET
, 0, 0);
358 LeaveCriticalSection( &This
->m_csClock
);
360 TRACE( "hr = %08lx\n", hr
);
365 static HRESULT WINAPI
366 IMediaFilter_fnGetSyncSource(IMediaFilter
* iface
,IReferenceClock
** ppobjClock
)
368 CFilterGraph_THIS(iface
,mediafilter
);
369 HRESULT hr
= VFW_E_NO_CLOCK
;
371 TRACE("(%p)->(%p)\n",This
,ppobjClock
);
373 if ( ppobjClock
== NULL
)
376 EnterCriticalSection( &This
->m_csClock
);
377 *ppobjClock
= This
->m_pClock
;
378 if ( This
->m_pClock
!= NULL
)
381 IReferenceClock_AddRef( This
->m_pClock
);
383 LeaveCriticalSection( &This
->m_csClock
);
385 TRACE( "hr = %08lx\n", hr
);
392 static ICOM_VTABLE(IMediaFilter
) imediafilter
=
394 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
395 /* IUnknown fields */
396 IMediaFilter_fnQueryInterface
,
397 IMediaFilter_fnAddRef
,
398 IMediaFilter_fnRelease
,
399 /* IPersist fields */
400 IMediaFilter_fnGetClassID
,
401 /* IMediaFilter fields */
403 IMediaFilter_fnPause
,
405 IMediaFilter_fnGetState
,
406 IMediaFilter_fnSetSyncSource
,
407 IMediaFilter_fnGetSyncSource
,
410 HRESULT
CFilterGraph_InitIMediaFilter( CFilterGraph
* pfg
)
414 ICOM_VTBL(&pfg
->mediafilter
) = &imediafilter
;
416 InitializeCriticalSection( &pfg
->m_csGraphState
);
417 InitializeCriticalSection( &pfg
->m_csClock
);
418 pfg
->m_stateGraph
= State_Stopped
;
419 pfg
->m_pClock
= NULL
;
424 void CFilterGraph_UninitIMediaFilter( CFilterGraph
* pfg
)
428 if ( pfg
->m_pClock
!= NULL
)
430 IReferenceClock_Release( pfg
->m_pClock
);
431 pfg
->m_pClock
= NULL
;
434 DeleteCriticalSection( &pfg
->m_csGraphState
);
435 DeleteCriticalSection( &pfg
->m_csClock
);