source: trunk/src/quartz/fgevent.c@ 8266

Last change on this file since 8266 was 6952, checked in by sandervl, 24 years ago

Wine 20011004 resync

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