2 * Implementation of IMediaFilter for FilterGraph.
6 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
39 #include "quartz_private.h"
43 #define WINE_QUARTZ_POLL_INTERVAL 10
45 /*****************************************************************************/
48 HRESULT CFilterGraph_PollGraphState(
56 *pState = State_Stopped;
58 EnterCriticalSection( &This->m_csGraphState );
59 EnterCriticalSection( &This->m_csFilters );
61 for ( n = 0; n < This->m_cActiveFilters; n++ )
63 hr = IBaseFilter_GetState( This->m_pActiveFilters[n].pFilter, (DWORD)0, pState );
68 LeaveCriticalSection( &This->m_csFilters );
69 LeaveCriticalSection( &This->m_csGraphState );
71 TRACE( "returns %08lx, state %d\n",
78 HRESULT CFilterGraph_StopGraph(
87 EnterCriticalSection( &This->m_csFilters );
89 for ( n = 0; n < This->m_cActiveFilters; n++ )
91 hrFilter = IBaseFilter_Stop( This->m_pActiveFilters[n].pFilter );
92 if ( hrFilter != S_OK )
99 LeaveCriticalSection( &This->m_csFilters );
105 HRESULT CFilterGraph_PauseGraph(
114 EnterCriticalSection( &This->m_csFilters );
116 for ( n = 0; n < This->m_cActiveFilters; n++ )
118 hrFilter = IBaseFilter_Pause( This->m_pActiveFilters[n].pFilter );
119 if ( hrFilter != S_OK )
126 LeaveCriticalSection( &This->m_csFilters );
132 HRESULT CFilterGraph_RunGraph(
133 CFilterGraph* This, REFERENCE_TIME rtStart )
141 EnterCriticalSection( &This->m_csFilters );
143 for ( n = 0; n < This->m_cActiveFilters; n++ )
145 hrFilter = IBaseFilter_Run( This->m_pActiveFilters[n].pFilter, rtStart );
146 if ( hrFilter != S_OK )
153 LeaveCriticalSection( &This->m_csFilters );
159 HRESULT CFilterGraph_SetSyncSourceGraph(
160 CFilterGraph* This, IReferenceClock* pClock )
168 EnterCriticalSection( &This->m_csFilters );
170 for ( n = 0; n < This->m_cActiveFilters; n++ )
172 hrFilter = IBaseFilter_SetSyncSource( This->m_pActiveFilters[n].pFilter, pClock );
173 if ( hrFilter == E_NOTIMPL )
175 if ( hrFilter != S_OK )
182 LeaveCriticalSection( &This->m_csFilters );
189 /*****************************************************************************/
191 static HRESULT WINAPI
192 IMediaFilter_fnQueryInterface(IMediaFilter* iface,REFIID riid,void** ppobj)
194 CFilterGraph_THIS(iface,mediafilter);
196 TRACE("(%p)->()\n",This);
198 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
202 IMediaFilter_fnAddRef(IMediaFilter* iface)
204 CFilterGraph_THIS(iface,mediafilter);
206 TRACE("(%p)->()\n",This);
208 return IUnknown_AddRef(This->unk.punkControl);
212 IMediaFilter_fnRelease(IMediaFilter* iface)
214 CFilterGraph_THIS(iface,mediafilter);
216 TRACE("(%p)->()\n",This);
218 return IUnknown_Release(This->unk.punkControl);
222 static HRESULT WINAPI
223 IMediaFilter_fnGetClassID(IMediaFilter* iface,CLSID* pclsid)
225 CFilterGraph_THIS(iface,mediafilter);
227 TRACE("(%p)->()\n",This);
229 return IPersist_GetClassID(
230 CFilterGraph_IPersist(This),pclsid);
233 static HRESULT WINAPI
234 IMediaFilter_fnStop(IMediaFilter* iface)
236 CFilterGraph_THIS(iface,mediafilter);
239 TRACE("(%p)->()\n",This);
243 EnterCriticalSection( &This->m_csGraphState );
245 if ( This->m_stateGraph != State_Stopped )
247 /* IDistributorNotify_Stop() */
249 hr = CFilterGraph_StopGraph(This);
251 This->m_stateGraph = State_Stopped;
254 LeaveCriticalSection( &This->m_csGraphState );
259 static HRESULT WINAPI
260 IMediaFilter_fnPause(IMediaFilter* iface)
262 CFilterGraph_THIS(iface,mediafilter);
265 TRACE("(%p)->()\n",This);
269 EnterCriticalSection( &This->m_csGraphState );
271 if ( This->m_stateGraph != State_Paused )
273 /* IDistributorNotify_Pause() */
275 hr = CFilterGraph_PauseGraph(This);
277 This->m_stateGraph = State_Paused;
279 (void)CFilterGraph_StopGraph(This);
282 LeaveCriticalSection( &This->m_csGraphState );
287 static HRESULT WINAPI
288 IMediaFilter_fnRun(IMediaFilter* iface,REFERENCE_TIME rtStart)
290 CFilterGraph_THIS(iface,mediafilter);
292 IReferenceClock* pClock;
294 TRACE("(%p)->()\n",This);
296 EnterCriticalSection( &This->m_csGraphState );
298 if ( This->m_stateGraph == State_Stopped )
300 hr = IMediaFilter_Pause(iface);
305 /* handle the special time. */
306 if ( rtStart == (REFERENCE_TIME)0 )
308 hr = IMediaFilter_GetSyncSource(iface,&pClock);
309 if ( hr == S_OK && pClock != NULL )
311 IReferenceClock_GetTime(pClock,&rtStart);
312 IReferenceClock_Release(pClock);
318 if ( This->m_stateGraph != State_Running )
320 /* IDistributorNotify_Run() */
322 hr = CFilterGraph_RunGraph(This,rtStart);
325 This->m_stateGraph = State_Running;
327 (void)CFilterGraph_StopGraph(This);
331 LeaveCriticalSection( &This->m_csGraphState );
336 static HRESULT WINAPI
337 IMediaFilter_fnGetState(IMediaFilter* iface,DWORD dwTimeOut,FILTER_STATE* pState)
339 CFilterGraph_THIS(iface,mediafilter);
344 TRACE("(%p)->(%p)\n",This,pState);
345 if ( pState == NULL )
348 dwTickStart = GetTickCount();
352 hr = CFilterGraph_PollGraphState( This, pState );
353 if ( hr != VFW_S_STATE_INTERMEDIATE )
355 if ( dwTimeOut == 0 )
358 Sleep( (dwTimeOut >= WINE_QUARTZ_POLL_INTERVAL) ?
359 WINE_QUARTZ_POLL_INTERVAL : dwTimeOut );
361 dwTickUsed = GetTickCount() - dwTickStart;
363 dwTickStart += dwTickUsed;
364 if ( dwTimeOut <= dwTickUsed )
367 dwTimeOut -= dwTickUsed;
370 EnterCriticalSection( &This->m_csGraphState );
371 *pState = This->m_stateGraph;
372 LeaveCriticalSection( &This->m_csGraphState );
377 static HRESULT WINAPI
378 IMediaFilter_fnSetSyncSource(IMediaFilter* iface,IReferenceClock* pobjClock)
380 CFilterGraph_THIS(iface,mediafilter);
381 HRESULT hr = NOERROR;
383 TRACE("(%p)->(%p)\n",This,pobjClock);
385 /* IDistributorNotify_SetSyncSource() */
387 EnterCriticalSection( &This->m_csClock );
389 hr = CFilterGraph_SetSyncSourceGraph( This, pobjClock );
393 if ( This->m_pClock != NULL )
395 IReferenceClock_Release(This->m_pClock);
396 This->m_pClock = NULL;
398 This->m_pClock = pobjClock;
399 if ( pobjClock != NULL )
400 IReferenceClock_AddRef( pobjClock );
401 IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This),
402 EC_CLOCK_CHANGED, 0, 0);
406 (void)CFilterGraph_SetSyncSourceGraph( This, This->m_pClock );
409 LeaveCriticalSection( &This->m_csClock );
411 TRACE( "hr = %08lx\n", hr );
416 static HRESULT WINAPI
417 IMediaFilter_fnGetSyncSource(IMediaFilter* iface,IReferenceClock** ppobjClock)
419 CFilterGraph_THIS(iface,mediafilter);
420 HRESULT hr = VFW_E_NO_CLOCK;
422 TRACE("(%p)->(%p)\n",This,ppobjClock);
424 if ( ppobjClock == NULL )
427 EnterCriticalSection( &This->m_csClock );
428 *ppobjClock = This->m_pClock;
429 if ( This->m_pClock != NULL )
432 IReferenceClock_AddRef( This->m_pClock );
434 LeaveCriticalSection( &This->m_csClock );
436 TRACE( "hr = %08lx\n", hr );
443 static ICOM_VTABLE(IMediaFilter) imediafilter =
445 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
446 /* IUnknown fields */
447 IMediaFilter_fnQueryInterface,
448 IMediaFilter_fnAddRef,
449 IMediaFilter_fnRelease,
450 /* IPersist fields */
451 IMediaFilter_fnGetClassID,
452 /* IMediaFilter fields */
454 IMediaFilter_fnPause,
456 IMediaFilter_fnGetState,
457 IMediaFilter_fnSetSyncSource,
458 IMediaFilter_fnGetSyncSource,
461 HRESULT CFilterGraph_InitIMediaFilter( CFilterGraph* pfg )
465 ICOM_VTBL(&pfg->mediafilter) = &imediafilter;
467 InitializeCriticalSection( &pfg->m_csGraphState );
468 InitializeCriticalSection( &pfg->m_csClock );
469 pfg->m_stateGraph = State_Stopped;
470 pfg->m_pClock = NULL;
475 void CFilterGraph_UninitIMediaFilter( CFilterGraph* pfg )
479 if ( pfg->m_pClock != NULL )
481 IReferenceClock_Release( pfg->m_pClock );
482 pfg->m_pClock = NULL;
485 DeleteCriticalSection( &pfg->m_csGraphState );
486 DeleteCriticalSection( &pfg->m_csClock );