Update shell xxxAW wrapper prototypes for fixed SHLWAPI functions.
[wine] / dlls / quartz / fgevent.c
1 /*
2  * CLSID_FilterGraph event handling.
3  *
4  * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winerror.h"
28 #include "strmif.h"
29 #include "control.h"
30 #include "evcode.h"
31 #include "uuids.h"
32 #include "vfwmsgs.h"
33
34 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
36
37 #include "quartz_private.h"
38 #include "fgraph.h"
39
40 #define EVENTQUEUE_BLOCKSIZE    2
41 #define EVENTQUEUE_MAX                  1024
42
43 struct FilterGraph_MEDIAEVENT
44 {
45         long            lEventCode;
46         LONG_PTR        lParam1;
47         LONG_PTR        lParam2;
48 };
49
50
51 static HRESULT FGEVENT_KeepEvent(
52         BOOL bKeep,
53         long lEventCode, LONG_PTR lParam1, LONG_PTR lParam2 )
54 {
55         switch ( lEventCode )
56         {
57         /*case EC_COMPLETE:*/
58         case EC_USERABORT:
59                 break;
60         case EC_ERRORABORT:
61                 break;
62         case EC_TIME:
63                 break;
64         /*case EC_REPAINT:*/
65         case EC_STREAM_ERROR_STOPPED:
66                 break;
67         case EC_STREAM_ERROR_STILLPLAYING:
68                 break;
69         case EC_ERROR_STILLPLAYING:
70                 break;
71         case EC_PALETTE_CHANGED:
72                 break;
73         case EC_VIDEO_SIZE_CHANGED:
74                 break;
75         case EC_QUALITY_CHANGE:
76                 break;
77         /*case EC_SHUTTING_DOWN:*/
78         case EC_CLOCK_CHANGED:
79                 break;
80         case EC_PAUSED:
81                 break;
82
83         case EC_OPENING_FILE:
84                 break;
85         case EC_BUFFERING_DATA:
86                 break;
87         case EC_FULLSCREEN_LOST:
88                 if ( bKeep )
89                 {
90                         if ( ((IBaseFilter*)lParam2) != NULL )
91                                 IBaseFilter_AddRef( (IBaseFilter*)lParam2 );
92                 }
93                 else
94                 {
95                         if ( ((IBaseFilter*)lParam2) != NULL )
96                                 IBaseFilter_Release( (IBaseFilter*)lParam2 );
97                 }
98                 break;
99         /*case EC_ACTIVATE:*/
100         /*case EC_NEED_RESTART:*/
101         /*case EC_WINDOW_DESTROYED:*/
102         /*case EC_DISPLAY_CHANGED:*/
103         /*case EC_STARVATION:*/
104         /*case EC_OLE_EVENT:*/
105         /*case EC_NOTIFY_WINDOW:*/
106         /*case EC_STREAM_CONTROL_STOPPED:*/
107         /*case EC_STREAM_CONTROL_STARTED:*/
108         /*case EC_END_OF_SEGMENT:*/
109         /*case EC_SEGMENT_STARTED:*/
110         case EC_LENGTH_CHANGED:
111                 break;
112         case EC_DEVICE_LOST:
113                 if ( bKeep )
114                 {
115                         if ( ((IUnknown*)lParam1) != NULL )
116                                 IUnknown_AddRef( (IUnknown*)lParam1 );
117                 }
118                 else
119                 {
120                         if ( ((IUnknown*)lParam1) != NULL )
121                                 IUnknown_Release( (IUnknown*)lParam1 );
122                 }
123                 break;
124
125         case EC_STEP_COMPLETE:
126                 break;
127         case EC_SKIP_FRAMES:
128                 break;
129
130         /*case EC_TIMECODE_AVAILABLE:*/
131         /*case EC_EXTDEVICE_MODE_CHANGE:*/
132
133         case EC_GRAPH_CHANGED:
134                 break;
135         case EC_CLOCK_UNSET:
136                 break;
137
138         default:
139                 if ( lEventCode < EC_USER )
140                 {
141                         FIXME( "unknown system event %08lx\n", lEventCode );
142                         return E_INVALIDARG;
143                 }
144                 TRACE( "user event %08lx\n", lEventCode );
145                 break;
146         }
147
148         return NOERROR;
149 }
150
151 /***************************************************************************
152  *
153  *      CLSID_FilterGraph::IMediaEvent[Ex]
154  *
155  */
156
157 static HRESULT WINAPI
158 IMediaEventEx_fnQueryInterface(IMediaEventEx* iface,REFIID riid,void** ppobj)
159 {
160         CFilterGraph_THIS(iface,mediaevent);
161
162         TRACE("(%p)->()\n",This);
163
164         return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
165 }
166
167 static ULONG WINAPI
168 IMediaEventEx_fnAddRef(IMediaEventEx* iface)
169 {
170         CFilterGraph_THIS(iface,mediaevent);
171
172         TRACE("(%p)->()\n",This);
173
174         return IUnknown_AddRef(This->unk.punkControl);
175 }
176
177 static ULONG WINAPI
178 IMediaEventEx_fnRelease(IMediaEventEx* iface)
179 {
180         CFilterGraph_THIS(iface,mediaevent);
181
182         TRACE("(%p)->()\n",This);
183
184         return IUnknown_Release(This->unk.punkControl);
185 }
186
187 static HRESULT WINAPI
188 IMediaEventEx_fnGetTypeInfoCount(IMediaEventEx* iface,UINT* pcTypeInfo)
189 {
190         CFilterGraph_THIS(iface,mediaevent);
191
192         FIXME("(%p)->()\n",This);
193
194         return E_NOTIMPL;
195 }
196
197 static HRESULT WINAPI
198 IMediaEventEx_fnGetTypeInfo(IMediaEventEx* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj)
199 {
200         CFilterGraph_THIS(iface,mediaevent);
201
202         FIXME("(%p)->()\n",This);
203
204         return E_NOTIMPL;
205 }
206
207 static HRESULT WINAPI
208 IMediaEventEx_fnGetIDsOfNames(IMediaEventEx* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId)
209 {
210         CFilterGraph_THIS(iface,mediaevent);
211
212         FIXME("(%p)->()\n",This);
213
214         return E_NOTIMPL;
215 }
216
217 static HRESULT WINAPI
218 IMediaEventEx_fnInvoke(IMediaEventEx* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr)
219 {
220         CFilterGraph_THIS(iface,mediaevent);
221
222         FIXME("(%p)->()\n",This);
223
224         return E_NOTIMPL;
225 }
226
227
228 static HRESULT WINAPI
229 IMediaEventEx_fnGetEventHandle(IMediaEventEx* iface,OAEVENT* hEvent)
230 {
231         CFilterGraph_THIS(iface,mediaevent);
232
233         TRACE("(%p)->()\n",This);
234
235         *hEvent = (OAEVENT)This->m_hMediaEvent;
236
237         return NOERROR;
238 }
239
240 static HRESULT WINAPI
241 IMediaEventEx_fnGetEvent(IMediaEventEx* iface,long* plEventCode,LONG_PTR* plParam1,LONG_PTR* plParam2,long lTimeOut)
242 {
243         CFilterGraph_THIS(iface,mediaevent);
244         ULONG cQueued;
245         DWORD dw;
246         DWORD dwStart;
247         HRESULT hr;
248         FilterGraph_MEDIAEVENT* pEvent;
249
250         TRACE("(%p)->(%p,%p,%p,%ld)\n",This,plEventCode,
251                 plParam1,plParam2,lTimeOut);
252
253         if ( plEventCode == NULL || plParam1 == NULL || plParam2 == NULL )
254                 return E_POINTER;
255
256         while ( 1 )
257         {
258                 dwStart = GetTickCount();
259                 dw = WaitForSingleObject( This->m_hMediaEvent, lTimeOut );
260                 if ( dw == WAIT_TIMEOUT )
261                         return VFW_E_TIMEOUT;
262                 if ( dw != WAIT_OBJECT_0 )
263                         return E_FAIL;
264
265                 EnterCriticalSection( &This->m_csMediaEvents );
266                 hr = S_FALSE;
267                 if ( This->m_cbMediaEventsMax > 0 )
268                 {
269                         cQueued =
270                                 (This->m_cbMediaEventsMax +
271                                  This->m_cbMediaEventsPut - This->m_cbMediaEventsGet) %
272                                         This->m_cbMediaEventsMax;
273                         if ( cQueued > 0 )
274                         {
275                                 pEvent = &This->m_pMediaEvents[This->m_cbMediaEventsGet];
276                                 *plEventCode = pEvent->lEventCode;
277                                 *plParam1 = pEvent->lParam1;
278                                 *plParam2 = pEvent->lParam2;
279                                 This->m_cbMediaEventsGet = (This->m_cbMediaEventsGet + 1) %
280                                                 This->m_cbMediaEventsMax;
281
282                                 hr = NOERROR;
283                                 if ( This->m_cbMediaEventsPut == This->m_cbMediaEventsGet )
284                                         ResetEvent( This->m_hMediaEvent );
285                         }
286                 }
287                 LeaveCriticalSection( &This->m_csMediaEvents );
288
289                 if ( hr != S_FALSE )
290                         return hr;
291                 if ( lTimeOut != INFINITE )
292                 {
293                         lTimeOut -= GetTickCount() - dwStart;
294                         if ( lTimeOut < 0 )
295                                 return VFW_E_TIMEOUT;
296                 }
297         }
298 }
299
300 static HRESULT WINAPI
301 IMediaEventEx_fnWaitForCompletion(IMediaEventEx* iface,long lTimeOut,long* plEventCode)
302 {
303         CFilterGraph_THIS(iface,mediaevent);
304         HRESULT hr;
305         long lEventCode;
306         LONG_PTR lParam1;
307         LONG_PTR lParam2;
308         DWORD dwTimePrev;
309         DWORD dwTimeCur;
310
311         TRACE("(%p)->(%ld,%p)\n",This,lTimeOut,plEventCode);
312
313         if ( plEventCode == NULL )
314                 return E_POINTER;
315         *plEventCode = 0;
316
317         dwTimePrev = GetTickCount();
318
319         while ( 1 )
320         {
321                 hr = IMediaEventEx_GetEvent(
322                                 CFilterGraph_IMediaEventEx(This),
323                                 &lEventCode,&lParam1,&lParam2,lTimeOut);
324                 if ( hr == VFW_E_TIMEOUT )
325                         hr = E_ABORT;
326                 if ( hr != NOERROR )
327                         return hr;
328                 IMediaEventEx_FreeEventParams(
329                                 CFilterGraph_IMediaEventEx(This),
330                                 lEventCode,lParam1,lParam2);
331
332                 if ( lEventCode == EC_COMPLETE ||
333                          lEventCode == EC_ERRORABORT ||
334                          lEventCode == EC_USERABORT )
335                 {
336                         *plEventCode = lEventCode;
337                         return NOERROR;
338                 }
339
340                 if ( lTimeOut != INFINITE )
341                 {
342                         dwTimeCur = GetTickCount();
343                         lTimeOut -= dwTimeCur - dwTimePrev;
344                         dwTimePrev = dwTimeCur;
345                         if ( lTimeOut < 0 )
346                                 return E_ABORT;
347                 }
348         }
349 }
350
351 static HRESULT WINAPI
352 IMediaEventEx_fnCancelDefaultHandling(IMediaEventEx* iface,long lEventCode)
353 {
354         CFilterGraph_THIS(iface,mediaevent);
355
356         FIXME("(%p)->() stub!\n",This);
357
358         return E_NOTIMPL;
359 }
360
361 static HRESULT WINAPI
362 IMediaEventEx_fnRestoreDefaultHandling(IMediaEventEx* iface,long lEventCode)
363 {
364         CFilterGraph_THIS(iface,mediaevent);
365
366         FIXME("(%p)->() stub!\n",This);
367
368         return E_NOTIMPL;
369 }
370
371 static HRESULT WINAPI
372 IMediaEventEx_fnFreeEventParams(IMediaEventEx* iface,long lEventCode,LONG_PTR lParam1,LONG_PTR lParam2)
373 {
374         CFilterGraph_THIS(iface,mediaevent);
375
376         TRACE("(%p)->(%08lx,%08x,%08x)\n",This,lEventCode,lParam1,lParam2);
377
378         return FGEVENT_KeepEvent( FALSE, lEventCode, lParam1, lParam2 );
379 }
380
381 static HRESULT WINAPI
382 IMediaEventEx_fnSetNotifyWindow(IMediaEventEx* iface,OAHWND hwnd,long message,LONG_PTR lParam)
383 {
384         CFilterGraph_THIS(iface,mediaevent);
385
386         TRACE("(%p)->(%08x,%08lx,%08x)\n",This,hwnd,message,lParam);
387
388         EnterCriticalSection( &This->m_csMediaEvents );
389         This->m_hwndEventNotify = (HWND)hwnd;
390         This->m_lEventNotifyMsg = message;
391         This->m_lEventNotifyParam = lParam;
392         LeaveCriticalSection( &This->m_csMediaEvents );
393
394         return NOERROR;
395 }
396
397 static HRESULT WINAPI
398 IMediaEventEx_fnSetNotifyFlags(IMediaEventEx* iface,long lNotifyFlags)
399 {
400         CFilterGraph_THIS(iface,mediaevent);
401
402         TRACE("(%p)->(%ld)\n",This,lNotifyFlags);
403
404         if ( lNotifyFlags != 0 && lNotifyFlags != 1 )
405                 return E_INVALIDARG;
406
407         EnterCriticalSection( &This->m_csMediaEvents );
408         This->m_lEventNotifyFlags = lNotifyFlags;
409         LeaveCriticalSection( &This->m_csMediaEvents );
410
411         return NOERROR;
412 }
413
414 static HRESULT WINAPI
415 IMediaEventEx_fnGetNotifyFlags(IMediaEventEx* iface,long* plNotifyFlags)
416 {
417         CFilterGraph_THIS(iface,mediaevent);
418
419         TRACE("(%p)->(%p)\n",This,plNotifyFlags);
420
421         if ( plNotifyFlags == NULL )
422                 return E_POINTER;
423
424         EnterCriticalSection( &This->m_csMediaEvents );
425         *plNotifyFlags = This->m_lEventNotifyFlags;
426         LeaveCriticalSection( &This->m_csMediaEvents );
427
428         return NOERROR;
429 }
430
431
432
433 static ICOM_VTABLE(IMediaEventEx) imediaevent =
434 {
435         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
436         /* IUnknown fields */
437         IMediaEventEx_fnQueryInterface,
438         IMediaEventEx_fnAddRef,
439         IMediaEventEx_fnRelease,
440         /* IDispatch fields */
441         IMediaEventEx_fnGetTypeInfoCount,
442         IMediaEventEx_fnGetTypeInfo,
443         IMediaEventEx_fnGetIDsOfNames,
444         IMediaEventEx_fnInvoke,
445         /* IMediaEvent fields */
446         IMediaEventEx_fnGetEventHandle,
447         IMediaEventEx_fnGetEvent,
448         IMediaEventEx_fnWaitForCompletion,
449         IMediaEventEx_fnCancelDefaultHandling,
450         IMediaEventEx_fnRestoreDefaultHandling,
451         IMediaEventEx_fnFreeEventParams,
452         /* IMediaEventEx fields */
453         IMediaEventEx_fnSetNotifyWindow,
454         IMediaEventEx_fnSetNotifyFlags,
455         IMediaEventEx_fnGetNotifyFlags,
456 };
457
458
459 HRESULT CFilterGraph_InitIMediaEventEx( CFilterGraph* pfg )
460 {
461         TRACE("(%p)\n",pfg);
462         ICOM_VTBL(&pfg->mediaevent) = &imediaevent;
463
464         pfg->m_hMediaEvent = CreateEventA( NULL, TRUE, FALSE, NULL );
465         if ( pfg->m_hMediaEvent == (HANDLE)NULL )
466                 return E_OUTOFMEMORY;
467
468         InitializeCriticalSection( &pfg->m_csMediaEvents );
469         pfg->m_pMediaEvents = NULL;
470         pfg->m_cbMediaEventsPut = 0;
471         pfg->m_cbMediaEventsGet = 0;
472         pfg->m_cbMediaEventsMax = 0;
473         pfg->m_hwndEventNotify = (HWND)NULL;
474         pfg->m_lEventNotifyMsg = 0;
475         pfg->m_lEventNotifyParam = 0;
476         pfg->m_lEventNotifyFlags = 0;
477
478         return NOERROR;
479 }
480
481 void CFilterGraph_UninitIMediaEventEx( CFilterGraph* pfg )
482 {
483         HRESULT hr;
484         long lEventCode;
485         LONG_PTR lParam1;
486         LONG_PTR lParam2;
487
488         TRACE("(%p)\n",pfg);
489
490         while ( 1 )
491         {
492                 hr = IMediaEventEx_GetEvent(
493                                 CFilterGraph_IMediaEventEx(pfg),
494                                 &lEventCode,&lParam1,&lParam2,0);
495                 if ( hr != NOERROR )
496                         break;
497                 IMediaEventEx_FreeEventParams(
498                                 CFilterGraph_IMediaEventEx(pfg),
499                                 lEventCode,lParam1,lParam2);
500         }
501
502         if ( pfg->m_pMediaEvents != NULL )
503         {
504                 QUARTZ_FreeMem( pfg->m_pMediaEvents );
505                 pfg->m_pMediaEvents = NULL;
506         }
507
508         DeleteCriticalSection( &pfg->m_csMediaEvents );
509         CloseHandle( pfg->m_hMediaEvent );
510 }
511
512 /***************************************************************************
513  *
514  *      CLSID_FilterGraph::IMediaEventSink
515  *
516  */
517
518 static HRESULT WINAPI
519 IMediaEventSink_fnQueryInterface(IMediaEventSink* iface,REFIID riid,void** ppobj)
520 {
521         CFilterGraph_THIS(iface,mediaeventsink);
522
523         TRACE("(%p)->()\n",This);
524
525         return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
526 }
527
528 static ULONG WINAPI
529 IMediaEventSink_fnAddRef(IMediaEventSink* iface)
530 {
531         CFilterGraph_THIS(iface,mediaeventsink);
532
533         TRACE("(%p)->()\n",This);
534
535         return IUnknown_AddRef(This->unk.punkControl);
536 }
537
538 static ULONG WINAPI
539 IMediaEventSink_fnRelease(IMediaEventSink* iface)
540 {
541         CFilterGraph_THIS(iface,mediaeventsink);
542
543         TRACE("(%p)->()\n",This);
544
545         return IUnknown_Release(This->unk.punkControl);
546 }
547
548 static HRESULT WINAPI
549 IMediaEventSink_fnNotify(IMediaEventSink* iface,long lEventCode,LONG_PTR lParam1,LONG_PTR lParam2)
550 {
551         CFilterGraph_THIS(iface,mediaeventsink);
552         HRESULT hr = NOERROR;
553         ULONG cQueued;
554         ULONG cTemp;
555         FilterGraph_MEDIAEVENT* pEvent;
556
557         TRACE("(%p)->(%08lx,%08x,%08x) stub!\n",This,lEventCode,lParam1,lParam2);
558
559         EnterCriticalSection( &This->m_csMediaEvents );
560
561         /* allocate a new entry. */
562         if ( This->m_cbMediaEventsMax == 0 )
563                 cQueued = 0;
564         else
565                 cQueued =
566                         (This->m_cbMediaEventsMax +
567                          This->m_cbMediaEventsPut - This->m_cbMediaEventsGet) %
568                                 This->m_cbMediaEventsMax;
569
570         if ( (cQueued + 1) >= This->m_cbMediaEventsMax )
571         {
572                 if ( This->m_cbMediaEventsMax >= EVENTQUEUE_MAX )
573                 {
574                         hr = E_FAIL;
575                         goto end;
576                 }
577                 pEvent = (FilterGraph_MEDIAEVENT*)
578                         QUARTZ_AllocMem( sizeof(FilterGraph_MEDIAEVENT) *
579                                 (This->m_cbMediaEventsMax+EVENTQUEUE_BLOCKSIZE) );
580                 if ( pEvent == NULL )
581                 {
582                         hr = E_OUTOFMEMORY;
583                         goto end;
584                 }
585                 if ( cQueued > 0 )
586                 {
587                         if ( (This->m_cbMediaEventsGet + cQueued) >=
588                                 This->m_cbMediaEventsMax )
589                         {
590                                 cTemp = This->m_cbMediaEventsMax - This->m_cbMediaEventsGet;
591                                 memcpy(
592                                         pEvent,
593                                         &This->m_pMediaEvents[This->m_cbMediaEventsGet],
594                                         sizeof(FilterGraph_MEDIAEVENT) * cTemp );
595                                 memcpy(
596                                         pEvent + cTemp,
597                                         &This->m_pMediaEvents[0],
598                                         sizeof(FilterGraph_MEDIAEVENT) * (cQueued - cTemp) );
599                         }
600                         else
601                         {
602                                 memcpy(
603                                         pEvent,
604                                         &This->m_pMediaEvents[This->m_cbMediaEventsGet],
605                                         sizeof(FilterGraph_MEDIAEVENT) * cQueued );
606                         }
607                         QUARTZ_FreeMem( This->m_pMediaEvents );
608                 }
609                 This->m_pMediaEvents = pEvent;
610                 This->m_cbMediaEventsMax += EVENTQUEUE_BLOCKSIZE;
611                 This->m_cbMediaEventsPut = cQueued;
612                 This->m_cbMediaEventsGet = 0;
613         }
614
615         /* duplicate params if necessary. */
616         hr = FGEVENT_KeepEvent( TRUE, lEventCode, lParam1, lParam2 );
617         if ( FAILED(hr) )
618                 goto end;
619
620         /* add to the queue. */
621         pEvent = &This->m_pMediaEvents[This->m_cbMediaEventsPut];
622         pEvent->lEventCode = lEventCode;
623         pEvent->lParam1 = lParam1;
624         pEvent->lParam2 = lParam2;
625         This->m_cbMediaEventsPut =
626                 (This->m_cbMediaEventsPut + 1) % This->m_cbMediaEventsMax;
627
628         SetEvent( This->m_hMediaEvent );
629         if ( This->m_hwndEventNotify != (HWND)NULL &&
630                  This->m_lEventNotifyFlags == 0 )
631         {
632                 PostMessageA(
633                         This->m_hwndEventNotify,
634                         This->m_lEventNotifyMsg,
635                         (WPARAM)0,
636                         (LPARAM)This->m_lEventNotifyParam );
637         }
638
639         hr = NOERROR;
640 end:
641         LeaveCriticalSection( &This->m_csMediaEvents );
642
643         return hr;
644 }
645
646
647 static ICOM_VTABLE(IMediaEventSink) imediaeventsink =
648 {
649         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
650         /* IUnknown fields */
651         IMediaEventSink_fnQueryInterface,
652         IMediaEventSink_fnAddRef,
653         IMediaEventSink_fnRelease,
654         /* IMediaEventSink fields */
655         IMediaEventSink_fnNotify,
656 };
657
658
659
660 HRESULT CFilterGraph_InitIMediaEventSink( CFilterGraph* pfg )
661 {
662         TRACE("(%p)\n",pfg);
663         ICOM_VTBL(&pfg->mediaeventsink) = &imediaeventsink;
664
665         return NOERROR;
666 }
667
668 void CFilterGraph_UninitIMediaEventSink( CFilterGraph* pfg )
669 {
670         TRACE("(%p)\n",pfg);
671 }
672