2 * CLSID_FilterGraph event handling.
4 * hidenori@a2.ctktv.ne.jp
20 #include "debugtools.h"
21 DEFAULT_DEBUG_CHANNEL(quartz);
23 #include "quartz_private.h"
26 #define EVENTQUEUE_BLOCKSIZE 2
27 #define EVENTQUEUE_MAX 1024
29 struct FilterGraph_MEDIAEVENT
37 static HRESULT FGEVENT_KeepEvent(
39 long lEventCode, LONG_PTR lParam1, LONG_PTR lParam2 )
51 case EC_STREAM_ERROR_STOPPED:
53 case EC_STREAM_ERROR_STILLPLAYING:
55 case EC_ERROR_STILLPLAYING:
57 case EC_PALETTE_CHANGED:
59 case EC_VIDEO_SIZE_CHANGED:
61 case EC_QUALITY_CHANGE:
63 /*case EC_SHUTTING_DOWN:*/
64 case EC_CLOCK_CHANGED:
71 case EC_BUFFERING_DATA:
73 case EC_FULLSCREEN_LOST:
76 if ( ((IBaseFilter*)lParam2) != NULL )
77 IBaseFilter_AddRef( (IBaseFilter*)lParam2 );
81 if ( ((IBaseFilter*)lParam2) != NULL )
82 IBaseFilter_Release( (IBaseFilter*)lParam2 );
86 /*case EC_NEED_RESTART:*/
87 /*case EC_WINDOW_DESTROYED:*/
88 /*case EC_DISPLAY_CHANGED:*/
89 /*case EC_STARVATION:*/
90 /*case EC_OLE_EVENT:*/
91 /*case EC_NOTIFY_WINDOW:*/
92 /*case EC_STREAM_CONTROL_STOPPED:*/
93 /*case EC_STREAM_CONTROL_STARTED:*/
94 /*case EC_END_OF_SEGMENT:*/
95 /*case EC_SEGMENT_STARTED:*/
96 case EC_LENGTH_CHANGED:
101 if ( ((IUnknown*)lParam1) != NULL )
102 IUnknown_AddRef( (IUnknown*)lParam1 );
106 if ( ((IUnknown*)lParam1) != NULL )
107 IUnknown_Release( (IUnknown*)lParam1 );
111 case EC_STEP_COMPLETE:
116 /*case EC_TIMECODE_AVAILABLE:*/
117 /*case EC_EXTDEVICE_MODE_CHANGE:*/
119 case EC_GRAPH_CHANGED:
125 if ( lEventCode < EC_USER )
127 FIXME( "unknown system event %08lx\n", lEventCode );
130 TRACE( "user event %08lx\n", lEventCode );
137 /***************************************************************************
139 * CLSID_FilterGraph::IMediaEvent[Ex]
143 static HRESULT WINAPI
144 IMediaEventEx_fnQueryInterface(IMediaEventEx* iface,REFIID riid,void** ppobj)
146 CFilterGraph_THIS(iface,mediaevent);
148 TRACE("(%p)->()\n",This);
150 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
154 IMediaEventEx_fnAddRef(IMediaEventEx* iface)
156 CFilterGraph_THIS(iface,mediaevent);
158 TRACE("(%p)->()\n",This);
160 return IUnknown_AddRef(This->unk.punkControl);
164 IMediaEventEx_fnRelease(IMediaEventEx* iface)
166 CFilterGraph_THIS(iface,mediaevent);
168 TRACE("(%p)->()\n",This);
170 return IUnknown_Release(This->unk.punkControl);
173 static HRESULT WINAPI
174 IMediaEventEx_fnGetTypeInfoCount(IMediaEventEx* iface,UINT* pcTypeInfo)
176 CFilterGraph_THIS(iface,mediaevent);
178 FIXME("(%p)->()\n",This);
183 static HRESULT WINAPI
184 IMediaEventEx_fnGetTypeInfo(IMediaEventEx* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj)
186 CFilterGraph_THIS(iface,mediaevent);
188 FIXME("(%p)->()\n",This);
193 static HRESULT WINAPI
194 IMediaEventEx_fnGetIDsOfNames(IMediaEventEx* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId)
196 CFilterGraph_THIS(iface,mediaevent);
198 FIXME("(%p)->()\n",This);
203 static HRESULT WINAPI
204 IMediaEventEx_fnInvoke(IMediaEventEx* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr)
206 CFilterGraph_THIS(iface,mediaevent);
208 FIXME("(%p)->()\n",This);
214 static HRESULT WINAPI
215 IMediaEventEx_fnGetEventHandle(IMediaEventEx* iface,OAEVENT* hEvent)
217 CFilterGraph_THIS(iface,mediaevent);
219 TRACE("(%p)->()\n",This);
221 *hEvent = (OAEVENT)This->m_hMediaEvent;
226 static HRESULT WINAPI
227 IMediaEventEx_fnGetEvent(IMediaEventEx* iface,long* plEventCode,LONG_PTR* plParam1,LONG_PTR* plParam2,long lTimeOut)
229 CFilterGraph_THIS(iface,mediaevent);
234 FilterGraph_MEDIAEVENT* pEvent;
236 TRACE("(%p)->(%p,%p,%p,%ld)\n",This,plEventCode,
237 plParam1,plParam2,lTimeOut);
239 if ( plEventCode == NULL || plParam1 == NULL || plParam2 == NULL )
244 dwStart = GetTickCount();
245 dw = WaitForSingleObject( This->m_hMediaEvent, lTimeOut );
246 if ( dw == WAIT_TIMEOUT )
247 return VFW_E_TIMEOUT;
248 if ( dw != WAIT_OBJECT_0 )
251 EnterCriticalSection( &This->m_csMediaEvents );
253 if ( This->m_cbMediaEventsMax > 0 )
256 (This->m_cbMediaEventsMax +
257 This->m_cbMediaEventsPut - This->m_cbMediaEventsGet) %
258 This->m_cbMediaEventsMax;
261 pEvent = &This->m_pMediaEvents[This->m_cbMediaEventsGet];
262 *plEventCode = pEvent->lEventCode;
263 *plParam1 = pEvent->lParam1;
264 *plParam2 = pEvent->lParam2;
265 This->m_cbMediaEventsGet = (This->m_cbMediaEventsGet + 1) %
266 This->m_cbMediaEventsMax;
269 if ( This->m_cbMediaEventsPut == This->m_cbMediaEventsGet )
270 ResetEvent( This->m_hMediaEvent );
273 LeaveCriticalSection( &This->m_csMediaEvents );
277 if ( lTimeOut != INFINITE )
279 lTimeOut -= GetTickCount() - dwStart;
281 return VFW_E_TIMEOUT;
286 static HRESULT WINAPI
287 IMediaEventEx_fnWaitForCompletion(IMediaEventEx* iface,long lTimeOut,long* plEventCode)
289 CFilterGraph_THIS(iface,mediaevent);
297 TRACE("(%p)->(%ld,%p)\n",This,lTimeOut,plEventCode);
299 if ( plEventCode == NULL )
303 dwTimePrev = GetTickCount();
307 hr = IMediaEventEx_GetEvent(
308 CFilterGraph_IMediaEventEx(This),
309 &lEventCode,&lParam1,&lParam2,lTimeOut);
310 if ( hr == VFW_E_TIMEOUT )
314 IMediaEventEx_FreeEventParams(
315 CFilterGraph_IMediaEventEx(This),
316 lEventCode,lParam1,lParam2);
318 if ( lEventCode == EC_COMPLETE ||
319 lEventCode == EC_ERRORABORT ||
320 lEventCode == EC_USERABORT )
322 *plEventCode = lEventCode;
326 if ( lTimeOut != INFINITE )
328 dwTimeCur = GetTickCount();
329 lTimeOut -= dwTimeCur - dwTimePrev;
330 dwTimePrev = dwTimeCur;
337 static HRESULT WINAPI
338 IMediaEventEx_fnCancelDefaultHandling(IMediaEventEx* iface,long lEventCode)
340 CFilterGraph_THIS(iface,mediaevent);
342 FIXME("(%p)->() stub!\n",This);
347 static HRESULT WINAPI
348 IMediaEventEx_fnRestoreDefaultHandling(IMediaEventEx* iface,long lEventCode)
350 CFilterGraph_THIS(iface,mediaevent);
352 FIXME("(%p)->() stub!\n",This);
357 static HRESULT WINAPI
358 IMediaEventEx_fnFreeEventParams(IMediaEventEx* iface,long lEventCode,LONG_PTR lParam1,LONG_PTR lParam2)
360 CFilterGraph_THIS(iface,mediaevent);
362 TRACE("(%p)->(%08lx,%08x,%08x)\n",This,lEventCode,lParam1,lParam2);
364 return FGEVENT_KeepEvent( FALSE, lEventCode, lParam1, lParam2 );
367 static HRESULT WINAPI
368 IMediaEventEx_fnSetNotifyWindow(IMediaEventEx* iface,OAHWND hwnd,long message,LONG_PTR lParam)
370 CFilterGraph_THIS(iface,mediaevent);
372 TRACE("(%p)->(%08x,%08lx,%08x)\n",This,hwnd,message,lParam);
374 EnterCriticalSection( &This->m_csMediaEvents );
375 This->m_hwndEventNotify = (HWND)hwnd;
376 This->m_lEventNotifyMsg = message;
377 This->m_lEventNotifyParam = lParam;
378 LeaveCriticalSection( &This->m_csMediaEvents );
383 static HRESULT WINAPI
384 IMediaEventEx_fnSetNotifyFlags(IMediaEventEx* iface,long lNotifyFlags)
386 CFilterGraph_THIS(iface,mediaevent);
388 TRACE("(%p)->(%ld)\n",This,lNotifyFlags);
390 if ( lNotifyFlags != 0 && lNotifyFlags != 1 )
393 EnterCriticalSection( &This->m_csMediaEvents );
394 This->m_lEventNotifyFlags = lNotifyFlags;
395 LeaveCriticalSection( &This->m_csMediaEvents );
400 static HRESULT WINAPI
401 IMediaEventEx_fnGetNotifyFlags(IMediaEventEx* iface,long* plNotifyFlags)
403 CFilterGraph_THIS(iface,mediaevent);
405 TRACE("(%p)->(%p)\n",This,plNotifyFlags);
407 if ( plNotifyFlags == NULL )
410 EnterCriticalSection( &This->m_csMediaEvents );
411 *plNotifyFlags = This->m_lEventNotifyFlags;
412 LeaveCriticalSection( &This->m_csMediaEvents );
419 static ICOM_VTABLE(IMediaEventEx) imediaevent =
421 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
422 /* IUnknown fields */
423 IMediaEventEx_fnQueryInterface,
424 IMediaEventEx_fnAddRef,
425 IMediaEventEx_fnRelease,
426 /* IDispatch fields */
427 IMediaEventEx_fnGetTypeInfoCount,
428 IMediaEventEx_fnGetTypeInfo,
429 IMediaEventEx_fnGetIDsOfNames,
430 IMediaEventEx_fnInvoke,
431 /* IMediaEvent fields */
432 IMediaEventEx_fnGetEventHandle,
433 IMediaEventEx_fnGetEvent,
434 IMediaEventEx_fnWaitForCompletion,
435 IMediaEventEx_fnCancelDefaultHandling,
436 IMediaEventEx_fnRestoreDefaultHandling,
437 IMediaEventEx_fnFreeEventParams,
438 /* IMediaEventEx fields */
439 IMediaEventEx_fnSetNotifyWindow,
440 IMediaEventEx_fnSetNotifyFlags,
441 IMediaEventEx_fnGetNotifyFlags,
445 HRESULT CFilterGraph_InitIMediaEventEx( CFilterGraph* pfg )
448 ICOM_VTBL(&pfg->mediaevent) = &imediaevent;
450 pfg->m_hMediaEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
451 if ( pfg->m_hMediaEvent == (HANDLE)NULL )
452 return E_OUTOFMEMORY;
454 InitializeCriticalSection( &pfg->m_csMediaEvents );
455 pfg->m_pMediaEvents = NULL;
456 pfg->m_cbMediaEventsPut = 0;
457 pfg->m_cbMediaEventsGet = 0;
458 pfg->m_cbMediaEventsMax = 0;
459 pfg->m_hwndEventNotify = (HWND)NULL;
460 pfg->m_lEventNotifyMsg = 0;
461 pfg->m_lEventNotifyParam = 0;
462 pfg->m_lEventNotifyFlags = 0;
467 void CFilterGraph_UninitIMediaEventEx( CFilterGraph* pfg )
478 hr = IMediaEventEx_GetEvent(
479 CFilterGraph_IMediaEventEx(pfg),
480 &lEventCode,&lParam1,&lParam2,0);
483 IMediaEventEx_FreeEventParams(
484 CFilterGraph_IMediaEventEx(pfg),
485 lEventCode,lParam1,lParam2);
488 if ( pfg->m_pMediaEvents != NULL )
490 QUARTZ_FreeMem( pfg->m_pMediaEvents );
491 pfg->m_pMediaEvents = NULL;
494 DeleteCriticalSection( &pfg->m_csMediaEvents );
495 CloseHandle( pfg->m_hMediaEvent );
498 /***************************************************************************
500 * CLSID_FilterGraph::IMediaEventSink
504 static HRESULT WINAPI
505 IMediaEventSink_fnQueryInterface(IMediaEventSink* iface,REFIID riid,void** ppobj)
507 CFilterGraph_THIS(iface,mediaeventsink);
509 TRACE("(%p)->()\n",This);
511 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
515 IMediaEventSink_fnAddRef(IMediaEventSink* iface)
517 CFilterGraph_THIS(iface,mediaeventsink);
519 TRACE("(%p)->()\n",This);
521 return IUnknown_AddRef(This->unk.punkControl);
525 IMediaEventSink_fnRelease(IMediaEventSink* iface)
527 CFilterGraph_THIS(iface,mediaeventsink);
529 TRACE("(%p)->()\n",This);
531 return IUnknown_Release(This->unk.punkControl);
534 static HRESULT WINAPI
535 IMediaEventSink_fnNotify(IMediaEventSink* iface,long lEventCode,LONG_PTR lParam1,LONG_PTR lParam2)
537 CFilterGraph_THIS(iface,mediaeventsink);
538 HRESULT hr = NOERROR;
541 FilterGraph_MEDIAEVENT* pEvent;
543 TRACE("(%p)->(%08lx,%08x,%08x) stub!\n",This,lEventCode,lParam1,lParam2);
545 EnterCriticalSection( &This->m_csMediaEvents );
547 /* allocate a new entry. */
548 if ( This->m_cbMediaEventsMax == 0 )
552 (This->m_cbMediaEventsMax +
553 This->m_cbMediaEventsPut - This->m_cbMediaEventsGet) %
554 This->m_cbMediaEventsMax;
556 if ( (cQueued + 1) >= This->m_cbMediaEventsMax )
558 if ( This->m_cbMediaEventsMax >= EVENTQUEUE_MAX )
563 pEvent = (FilterGraph_MEDIAEVENT*)
564 QUARTZ_AllocMem( sizeof(FilterGraph_MEDIAEVENT) *
565 (This->m_cbMediaEventsMax+EVENTQUEUE_BLOCKSIZE) );
566 if ( pEvent == NULL )
573 if ( (This->m_cbMediaEventsGet + cQueued) >=
574 This->m_cbMediaEventsMax )
576 cTemp = This->m_cbMediaEventsMax - This->m_cbMediaEventsGet;
579 &This->m_pMediaEvents[This->m_cbMediaEventsGet],
580 sizeof(FilterGraph_MEDIAEVENT) * cTemp );
583 &This->m_pMediaEvents[0],
584 sizeof(FilterGraph_MEDIAEVENT) * (cQueued - cTemp) );
590 &This->m_pMediaEvents[This->m_cbMediaEventsGet],
591 sizeof(FilterGraph_MEDIAEVENT) * cQueued );
593 QUARTZ_FreeMem( This->m_pMediaEvents );
595 This->m_pMediaEvents = pEvent;
596 This->m_cbMediaEventsMax += EVENTQUEUE_BLOCKSIZE;
597 This->m_cbMediaEventsPut = cQueued;
598 This->m_cbMediaEventsGet = 0;
601 /* duplicate params if necessary. */
602 hr = FGEVENT_KeepEvent( TRUE, lEventCode, lParam1, lParam2 );
606 /* add to the queue. */
607 pEvent = &This->m_pMediaEvents[This->m_cbMediaEventsPut];
608 pEvent->lEventCode = lEventCode;
609 pEvent->lParam1 = lParam1;
610 pEvent->lParam2 = lParam2;
611 This->m_cbMediaEventsPut =
612 (This->m_cbMediaEventsPut + 1) % This->m_cbMediaEventsMax;
614 SetEvent( This->m_hMediaEvent );
615 if ( This->m_hwndEventNotify != (HWND)NULL &&
616 This->m_lEventNotifyFlags == 0 )
619 This->m_hwndEventNotify,
620 This->m_lEventNotifyMsg,
622 (LPARAM)This->m_lEventNotifyParam );
627 LeaveCriticalSection( &This->m_csMediaEvents );
633 static ICOM_VTABLE(IMediaEventSink) imediaeventsink =
635 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
636 /* IUnknown fields */
637 IMediaEventSink_fnQueryInterface,
638 IMediaEventSink_fnAddRef,
639 IMediaEventSink_fnRelease,
640 /* IMediaEventSink fields */
641 IMediaEventSink_fnNotify,
646 HRESULT CFilterGraph_InitIMediaEventSink( CFilterGraph* pfg )
649 ICOM_VTBL(&pfg->mediaeventsink) = &imediaeventsink;
654 void CFilterGraph_UninitIMediaEventSink( CFilterGraph* pfg )