2 * CLSID_FilterGraph event handling.
4 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
37 #include "quartz_private.h"
40 #define EVENTQUEUE_BLOCKSIZE 2
41 #define EVENTQUEUE_MAX 1024
43 struct FilterGraph_MEDIAEVENT
51 static HRESULT FGEVENT_KeepEvent(
53 long lEventCode, LONG_PTR lParam1, LONG_PTR lParam2 )
65 case EC_STREAM_ERROR_STOPPED:
67 case EC_STREAM_ERROR_STILLPLAYING:
69 case EC_ERROR_STILLPLAYING:
71 case EC_PALETTE_CHANGED:
73 case EC_VIDEO_SIZE_CHANGED:
75 case EC_QUALITY_CHANGE:
77 /*case EC_SHUTTING_DOWN:*/
78 case EC_CLOCK_CHANGED:
83 case EC_BUFFERING_DATA:
85 case EC_FULLSCREEN_LOST:
88 if ( ((IBaseFilter*)lParam2) != NULL )
89 IBaseFilter_AddRef( (IBaseFilter*)lParam2 );
93 if ( ((IBaseFilter*)lParam2) != NULL )
94 IBaseFilter_Release( (IBaseFilter*)lParam2 );
98 /*case EC_NEED_RESTART:*/
99 /*case EC_WINDOW_DESTROYED:*/
100 /*case EC_DISPLAY_CHANGED:*/
101 /*case EC_STARVATION:*/
102 /*case EC_OLE_EVENT:*/
103 /*case EC_NOTIFY_WINDOW:*/
104 /*case EC_STREAM_CONTROL_STOPPED:*/
105 /*case EC_STREAM_CONTROL_STARTED:*/
106 /*case EC_END_OF_SEGMENT:*/
107 /*case EC_SEGMENT_STARTED:*/
108 case EC_LENGTH_CHANGED:
112 if ( lEventCode < EC_USER )
114 FIXME( "unknown system event %08lx\n", lEventCode );
117 TRACE( "user event %08lx\n", lEventCode );
124 /***************************************************************************
126 * CLSID_FilterGraph::IMediaEvent[Ex]
130 static HRESULT WINAPI
131 IMediaEventEx_fnQueryInterface(IMediaEventEx* iface,REFIID riid,void** ppobj)
133 CFilterGraph_THIS(iface,mediaevent);
135 TRACE("(%p)->()\n",This);
137 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
141 IMediaEventEx_fnAddRef(IMediaEventEx* iface)
143 CFilterGraph_THIS(iface,mediaevent);
145 TRACE("(%p)->()\n",This);
147 return IUnknown_AddRef(This->unk.punkControl);
151 IMediaEventEx_fnRelease(IMediaEventEx* iface)
153 CFilterGraph_THIS(iface,mediaevent);
155 TRACE("(%p)->()\n",This);
157 return IUnknown_Release(This->unk.punkControl);
160 static HRESULT WINAPI
161 IMediaEventEx_fnGetTypeInfoCount(IMediaEventEx* iface,UINT* pcTypeInfo)
163 CFilterGraph_THIS(iface,mediaevent);
165 FIXME("(%p)->()\n",This);
170 static HRESULT WINAPI
171 IMediaEventEx_fnGetTypeInfo(IMediaEventEx* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj)
173 CFilterGraph_THIS(iface,mediaevent);
175 FIXME("(%p)->()\n",This);
180 static HRESULT WINAPI
181 IMediaEventEx_fnGetIDsOfNames(IMediaEventEx* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId)
183 CFilterGraph_THIS(iface,mediaevent);
185 FIXME("(%p)->()\n",This);
190 static HRESULT WINAPI
191 IMediaEventEx_fnInvoke(IMediaEventEx* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr)
193 CFilterGraph_THIS(iface,mediaevent);
195 FIXME("(%p)->()\n",This);
201 static HRESULT WINAPI
202 IMediaEventEx_fnGetEventHandle(IMediaEventEx* iface,OAEVENT* hEvent)
204 CFilterGraph_THIS(iface,mediaevent);
206 TRACE("(%p)->()\n",This);
208 *hEvent = (OAEVENT)This->m_hMediaEvent;
213 static HRESULT WINAPI
214 IMediaEventEx_fnGetEvent(IMediaEventEx* iface,long* plEventCode,LONG_PTR* plParam1,LONG_PTR* plParam2,long lTimeOut)
216 CFilterGraph_THIS(iface,mediaevent);
221 FilterGraph_MEDIAEVENT* pEvent;
223 TRACE("(%p)->(%p,%p,%p,%ld)\n",This,plEventCode,
224 plParam1,plParam2,lTimeOut);
226 if ( plEventCode == NULL || plParam1 == NULL || plParam2 == NULL )
231 dwStart = GetTickCount();
232 dw = WaitForSingleObject( This->m_hMediaEvent, lTimeOut );
233 if ( dw == WAIT_TIMEOUT )
234 return VFW_E_TIMEOUT;
235 if ( dw != WAIT_OBJECT_0 )
238 EnterCriticalSection( &This->m_csMediaEvents );
240 if ( This->m_cbMediaEventsMax > 0 )
243 (This->m_cbMediaEventsMax +
244 This->m_cbMediaEventsPut - This->m_cbMediaEventsGet) %
245 This->m_cbMediaEventsMax;
248 pEvent = &This->m_pMediaEvents[This->m_cbMediaEventsGet];
249 *plEventCode = pEvent->lEventCode;
250 *plParam1 = pEvent->lParam1;
251 *plParam2 = pEvent->lParam2;
252 This->m_cbMediaEventsGet = (This->m_cbMediaEventsGet + 1) %
253 This->m_cbMediaEventsMax;
256 if ( This->m_cbMediaEventsPut == This->m_cbMediaEventsGet )
257 ResetEvent( This->m_hMediaEvent );
260 LeaveCriticalSection( &This->m_csMediaEvents );
264 if ( lTimeOut != INFINITE )
266 lTimeOut -= GetTickCount() - dwStart;
268 return VFW_E_TIMEOUT;
273 static HRESULT WINAPI
274 IMediaEventEx_fnWaitForCompletion(IMediaEventEx* iface,long lTimeOut,long* plEventCode)
276 CFilterGraph_THIS(iface,mediaevent);
284 TRACE("(%p)->(%ld,%p)\n",This,lTimeOut,plEventCode);
286 if ( plEventCode == NULL )
290 dwTimePrev = GetTickCount();
294 hr = IMediaEventEx_GetEvent(
295 CFilterGraph_IMediaEventEx(This),
296 &lEventCode,&lParam1,&lParam2,lTimeOut);
297 if ( hr == VFW_E_TIMEOUT )
301 IMediaEventEx_FreeEventParams(
302 CFilterGraph_IMediaEventEx(This),
303 lEventCode,lParam1,lParam2);
305 if ( lEventCode == EC_COMPLETE ||
306 lEventCode == EC_ERRORABORT ||
307 lEventCode == EC_USERABORT )
309 *plEventCode = lEventCode;
313 if ( lTimeOut != INFINITE )
315 dwTimeCur = GetTickCount();
316 lTimeOut -= dwTimeCur - dwTimePrev;
317 dwTimePrev = dwTimeCur;
324 static HRESULT WINAPI
325 IMediaEventEx_fnCancelDefaultHandling(IMediaEventEx* iface,long lEventCode)
327 CFilterGraph_THIS(iface,mediaevent);
329 FIXME("(%p)->() stub!\n",This);
334 static HRESULT WINAPI
335 IMediaEventEx_fnRestoreDefaultHandling(IMediaEventEx* iface,long lEventCode)
337 CFilterGraph_THIS(iface,mediaevent);
339 FIXME("(%p)->() stub!\n",This);
344 static HRESULT WINAPI
345 IMediaEventEx_fnFreeEventParams(IMediaEventEx* iface,long lEventCode,LONG_PTR lParam1,LONG_PTR lParam2)
347 CFilterGraph_THIS(iface,mediaevent);
349 TRACE("(%p)->(%08lx,%08x,%08x)\n",This,lEventCode,lParam1,lParam2);
351 return FGEVENT_KeepEvent( FALSE, lEventCode, lParam1, lParam2 );
354 static HRESULT WINAPI
355 IMediaEventEx_fnSetNotifyWindow(IMediaEventEx* iface,OAHWND hwnd,long message,LONG_PTR lParam)
357 CFilterGraph_THIS(iface,mediaevent);
359 TRACE("(%p)->(%08x,%08lx,%08x)\n",This,hwnd,message,lParam);
361 EnterCriticalSection( &This->m_csMediaEvents );
362 This->m_hwndEventNotify = (HWND)hwnd;
363 This->m_lEventNotifyMsg = message;
364 This->m_lEventNotifyParam = lParam;
365 LeaveCriticalSection( &This->m_csMediaEvents );
370 static HRESULT WINAPI
371 IMediaEventEx_fnSetNotifyFlags(IMediaEventEx* iface,long lNotifyFlags)
373 CFilterGraph_THIS(iface,mediaevent);
375 TRACE("(%p)->(%ld)\n",This,lNotifyFlags);
377 if ( lNotifyFlags != 0 && lNotifyFlags != 1 )
380 EnterCriticalSection( &This->m_csMediaEvents );
381 This->m_lEventNotifyFlags = lNotifyFlags;
382 LeaveCriticalSection( &This->m_csMediaEvents );
387 static HRESULT WINAPI
388 IMediaEventEx_fnGetNotifyFlags(IMediaEventEx* iface,long* plNotifyFlags)
390 CFilterGraph_THIS(iface,mediaevent);
392 TRACE("(%p)->(%p)\n",This,plNotifyFlags);
394 if ( plNotifyFlags == NULL )
397 EnterCriticalSection( &This->m_csMediaEvents );
398 *plNotifyFlags = This->m_lEventNotifyFlags;
399 LeaveCriticalSection( &This->m_csMediaEvents );
406 static ICOM_VTABLE(IMediaEventEx) imediaevent =
408 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
409 /* IUnknown fields */
410 IMediaEventEx_fnQueryInterface,
411 IMediaEventEx_fnAddRef,
412 IMediaEventEx_fnRelease,
413 /* IDispatch fields */
414 IMediaEventEx_fnGetTypeInfoCount,
415 IMediaEventEx_fnGetTypeInfo,
416 IMediaEventEx_fnGetIDsOfNames,
417 IMediaEventEx_fnInvoke,
418 /* IMediaEvent fields */
419 IMediaEventEx_fnGetEventHandle,
420 IMediaEventEx_fnGetEvent,
421 IMediaEventEx_fnWaitForCompletion,
422 IMediaEventEx_fnCancelDefaultHandling,
423 IMediaEventEx_fnRestoreDefaultHandling,
424 IMediaEventEx_fnFreeEventParams,
425 /* IMediaEventEx fields */
426 IMediaEventEx_fnSetNotifyWindow,
427 IMediaEventEx_fnSetNotifyFlags,
428 IMediaEventEx_fnGetNotifyFlags,
432 HRESULT CFilterGraph_InitIMediaEventEx( CFilterGraph* pfg )
435 ICOM_VTBL(&pfg->mediaevent) = &imediaevent;
437 pfg->m_hMediaEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
438 if ( pfg->m_hMediaEvent == (HANDLE)NULL )
439 return E_OUTOFMEMORY;
441 InitializeCriticalSection( &pfg->m_csMediaEvents );
442 pfg->m_pMediaEvents = NULL;
443 pfg->m_cbMediaEventsPut = 0;
444 pfg->m_cbMediaEventsGet = 0;
445 pfg->m_cbMediaEventsMax = 0;
446 pfg->m_hwndEventNotify = (HWND)NULL;
447 pfg->m_lEventNotifyMsg = 0;
448 pfg->m_lEventNotifyParam = 0;
449 pfg->m_lEventNotifyFlags = 0;
454 void CFilterGraph_UninitIMediaEventEx( CFilterGraph* pfg )
465 hr = IMediaEventEx_GetEvent(
466 CFilterGraph_IMediaEventEx(pfg),
467 &lEventCode,&lParam1,&lParam2,0);
470 IMediaEventEx_FreeEventParams(
471 CFilterGraph_IMediaEventEx(pfg),
472 lEventCode,lParam1,lParam2);
475 if ( pfg->m_pMediaEvents != NULL )
477 QUARTZ_FreeMem( pfg->m_pMediaEvents );
478 pfg->m_pMediaEvents = NULL;
481 DeleteCriticalSection( &pfg->m_csMediaEvents );
482 CloseHandle( pfg->m_hMediaEvent );
485 /***************************************************************************
487 * CLSID_FilterGraph::IMediaEventSink
491 static HRESULT WINAPI
492 IMediaEventSink_fnQueryInterface(IMediaEventSink* iface,REFIID riid,void** ppobj)
494 CFilterGraph_THIS(iface,mediaeventsink);
496 TRACE("(%p)->()\n",This);
498 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
502 IMediaEventSink_fnAddRef(IMediaEventSink* iface)
504 CFilterGraph_THIS(iface,mediaeventsink);
506 TRACE("(%p)->()\n",This);
508 return IUnknown_AddRef(This->unk.punkControl);
512 IMediaEventSink_fnRelease(IMediaEventSink* iface)
514 CFilterGraph_THIS(iface,mediaeventsink);
516 TRACE("(%p)->()\n",This);
518 return IUnknown_Release(This->unk.punkControl);
521 static HRESULT WINAPI
522 IMediaEventSink_fnNotify(IMediaEventSink* iface,long lEventCode,LONG_PTR lParam1,LONG_PTR lParam2)
524 CFilterGraph_THIS(iface,mediaeventsink);
525 HRESULT hr = NOERROR;
528 FilterGraph_MEDIAEVENT* pEvent;
530 TRACE("(%p)->(%08lx,%08x,%08x) stub!\n",This,lEventCode,lParam1,lParam2);
532 EnterCriticalSection( &This->m_csMediaEvents );
534 /* allocate a new entry. */
535 if ( This->m_cbMediaEventsMax == 0 )
539 (This->m_cbMediaEventsMax +
540 This->m_cbMediaEventsPut - This->m_cbMediaEventsGet) %
541 This->m_cbMediaEventsMax;
543 if ( (cQueued + 1) >= This->m_cbMediaEventsMax )
545 if ( This->m_cbMediaEventsMax >= EVENTQUEUE_MAX )
550 pEvent = (FilterGraph_MEDIAEVENT*)
551 QUARTZ_AllocMem( sizeof(FilterGraph_MEDIAEVENT) *
552 (This->m_cbMediaEventsMax+EVENTQUEUE_BLOCKSIZE) );
553 if ( pEvent == NULL )
560 if ( (This->m_cbMediaEventsGet + cQueued) >=
561 This->m_cbMediaEventsMax )
563 cTemp = This->m_cbMediaEventsMax - This->m_cbMediaEventsGet;
566 &This->m_pMediaEvents[This->m_cbMediaEventsGet],
567 sizeof(FilterGraph_MEDIAEVENT) * cTemp );
570 &This->m_pMediaEvents[0],
571 sizeof(FilterGraph_MEDIAEVENT) * (cQueued - cTemp) );
577 &This->m_pMediaEvents[This->m_cbMediaEventsGet],
578 sizeof(FilterGraph_MEDIAEVENT) * cQueued );
580 QUARTZ_FreeMem( This->m_pMediaEvents );
582 This->m_pMediaEvents = pEvent;
583 This->m_cbMediaEventsMax += EVENTQUEUE_BLOCKSIZE;
584 This->m_cbMediaEventsPut = cQueued;
585 This->m_cbMediaEventsGet = 0;
588 /* duplicate params if necessary. */
589 hr = FGEVENT_KeepEvent( TRUE, lEventCode, lParam1, lParam2 );
593 /* add to the queue. */
594 pEvent = &This->m_pMediaEvents[This->m_cbMediaEventsPut];
595 pEvent->lEventCode = lEventCode;
596 pEvent->lParam1 = lParam1;
597 pEvent->lParam2 = lParam2;
598 This->m_cbMediaEventsPut =
599 (This->m_cbMediaEventsPut + 1) % This->m_cbMediaEventsMax;
601 SetEvent( This->m_hMediaEvent );
602 if ( This->m_hwndEventNotify != (HWND)NULL &&
603 This->m_lEventNotifyFlags == 0 )
606 This->m_hwndEventNotify,
607 This->m_lEventNotifyMsg,
609 (LPARAM)This->m_lEventNotifyParam );
614 LeaveCriticalSection( &This->m_csMediaEvents );
620 static ICOM_VTABLE(IMediaEventSink) imediaeventsink =
622 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
623 /* IUnknown fields */
624 IMediaEventSink_fnQueryInterface,
625 IMediaEventSink_fnAddRef,
626 IMediaEventSink_fnRelease,
627 /* IMediaEventSink fields */
628 IMediaEventSink_fnNotify,
633 HRESULT CFilterGraph_InitIMediaEventSink( CFilterGraph* pfg )
636 ICOM_VTBL(&pfg->mediaeventsink) = &imediaeventsink;
641 void CFilterGraph_UninitIMediaEventSink( CFilterGraph* pfg )