Add missing cast.
[wine] / dlls / quartz / basefilt.c
1 /*
2  * Implements IBaseFilter. (internal)
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 "strmif.h"
15 #include "vfwmsgs.h"
16
17 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(quartz);
19
20 #include "quartz_private.h"
21 #include "basefilt.h"
22 #include "enumunk.h"
23
24
25 /***************************************************************************
26  *
27  *      CBaseFilterImpl::IBaseFilter
28  *
29  */
30
31 static HRESULT WINAPI
32 CBaseFilterImpl_fnQueryInterface(IBaseFilter* iface,REFIID riid,void** ppobj)
33 {
34         ICOM_THIS(CBaseFilterImpl,iface);
35
36         TRACE("(%p)->()\n",This);
37
38         return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
39 }
40
41 static ULONG WINAPI
42 CBaseFilterImpl_fnAddRef(IBaseFilter* iface)
43 {
44         ICOM_THIS(CBaseFilterImpl,iface);
45
46         TRACE("(%p)->()\n",This);
47
48         return IUnknown_AddRef(This->punkControl);
49 }
50
51 static ULONG WINAPI
52 CBaseFilterImpl_fnRelease(IBaseFilter* iface)
53 {
54         ICOM_THIS(CBaseFilterImpl,iface);
55
56         TRACE("(%p)->()\n",This);
57
58         return IUnknown_Release(This->punkControl);
59 }
60
61
62 static HRESULT WINAPI
63 CBaseFilterImpl_fnGetClassID(IBaseFilter* iface,CLSID* pclsid)
64 {
65         ICOM_THIS(CBaseFilterImpl,iface);
66
67         TRACE("(%p)->()\n",This);
68
69         if ( pclsid == NULL )
70                 return E_POINTER;
71
72         memcpy( pclsid, This->pclsidFilter, sizeof(CLSID) );
73
74         return NOERROR;
75 }
76
77 static HRESULT WINAPI
78 CBaseFilterImpl_fnStop(IBaseFilter* iface)
79 {
80         ICOM_THIS(CBaseFilterImpl,iface);
81         HRESULT hr;
82
83         TRACE("(%p)->()\n",This);
84
85         hr = NOERROR;
86
87         EnterCriticalSection( &This->csFilter );
88         TRACE("(%p) state = %d\n",This,This->fstate);
89
90         if ( This->fstate == State_Running )
91         {
92                 if ( This->pHandlers->pOnInactive != NULL )
93                         hr = This->pHandlers->pOnInactive( This );
94                 if ( SUCCEEDED(hr) )
95                         This->fstate = State_Paused;
96         }
97         if ( This->fstate == State_Paused )
98         {
99                 if ( This->pHandlers->pOnStop != NULL )
100                         hr = This->pHandlers->pOnStop( This );
101                 if ( SUCCEEDED(hr) )
102                         This->fstate = State_Stopped;
103         }
104
105         LeaveCriticalSection( &This->csFilter );
106
107         return hr;
108 }
109
110 static HRESULT WINAPI
111 CBaseFilterImpl_fnPause(IBaseFilter* iface)
112 {
113         ICOM_THIS(CBaseFilterImpl,iface);
114         HRESULT hr;
115
116         TRACE("(%p)->()\n",This);
117
118         hr = NOERROR;
119
120         EnterCriticalSection( &This->csFilter );
121         TRACE("(%p) state = %d\n",This,This->fstate);
122
123         if ( This->fstate != State_Paused )
124         {
125                 if ( This->pHandlers->pOnInactive != NULL )
126                         hr = This->pHandlers->pOnInactive( This );
127                 if ( SUCCEEDED(hr) )
128                         This->fstate = State_Paused;
129         }
130         LeaveCriticalSection( &This->csFilter );
131
132         TRACE("hr = %08lx\n",hr);
133
134         return hr;
135 }
136
137 static HRESULT WINAPI
138 CBaseFilterImpl_fnRun(IBaseFilter* iface,REFERENCE_TIME rtStart)
139 {
140         ICOM_THIS(CBaseFilterImpl,iface);
141         HRESULT hr;
142
143         TRACE("(%p)->()\n",This);
144
145         hr = NOERROR;
146
147         EnterCriticalSection( &This->csFilter );
148         TRACE("(%p) state = %d\n",This,This->fstate);
149
150         This->rtStart = rtStart;
151
152         if ( This->fstate == State_Stopped )
153         {
154                 if ( This->pHandlers->pOnInactive != NULL )
155                         hr = This->pHandlers->pOnInactive( This );
156                 if ( SUCCEEDED(hr) )
157                         This->fstate = State_Paused;
158         }
159         if ( This->fstate == State_Paused )
160         {
161                 if ( This->pHandlers->pOnActive != NULL )
162                         hr = This->pHandlers->pOnActive( This );
163                 if ( SUCCEEDED(hr) )
164                         This->fstate = State_Running;
165         }
166
167         LeaveCriticalSection( &This->csFilter );
168
169         return hr;
170 }
171
172 static HRESULT WINAPI
173 CBaseFilterImpl_fnGetState(IBaseFilter* iface,DWORD dw,FILTER_STATE* pState)
174 {
175         ICOM_THIS(CBaseFilterImpl,iface);
176
177         TRACE("(%p)->(%p)\n",This,pState);
178
179         if ( pState == NULL )
180                 return E_POINTER;
181
182         /* FIXME - ignore 'intermediate state' now */
183
184         EnterCriticalSection( &This->csFilter );
185         TRACE("(%p) state = %d\n",This,This->fstate);
186         *pState = This->fstate;
187         LeaveCriticalSection( &This->csFilter );
188
189         return NOERROR;
190 }
191
192 static HRESULT WINAPI
193 CBaseFilterImpl_fnSetSyncSource(IBaseFilter* iface,IReferenceClock* pobjClock)
194 {
195         ICOM_THIS(CBaseFilterImpl,iface);
196
197         TRACE("(%p)->(%p)\n",This,pobjClock);
198
199         EnterCriticalSection( &This->csFilter );
200
201         if ( This->pClock != NULL )
202         {
203                 IReferenceClock_Release( This->pClock );
204                 This->pClock = NULL;
205         }
206
207         This->pClock = pobjClock;
208         if ( pobjClock != NULL )
209                 IReferenceClock_AddRef( pobjClock );
210
211         LeaveCriticalSection( &This->csFilter );
212
213         return NOERROR;
214 }
215
216 static HRESULT WINAPI
217 CBaseFilterImpl_fnGetSyncSource(IBaseFilter* iface,IReferenceClock** ppobjClock)
218 {
219         ICOM_THIS(CBaseFilterImpl,iface);
220         HRESULT hr = VFW_E_NO_CLOCK;
221
222         TRACE("(%p)->(%p)\n",This,ppobjClock);
223
224         if ( ppobjClock == NULL )
225                 return E_POINTER;
226
227         EnterCriticalSection( &This->csFilter );
228
229         *ppobjClock = This->pClock;
230         if ( This->pClock != NULL )
231         {
232                 hr = NOERROR;
233                 IReferenceClock_AddRef( This->pClock );
234         }
235
236         LeaveCriticalSection( &This->csFilter );
237
238         return hr;
239 }
240
241
242 static HRESULT WINAPI
243 CBaseFilterImpl_fnEnumPins(IBaseFilter* iface,IEnumPins** ppenum)
244 {
245         ICOM_THIS(CBaseFilterImpl,iface);
246         HRESULT hr = E_FAIL;
247         QUARTZ_CompList*        pListPins;
248         QUARTZ_CompListItem*    pItem;
249         IUnknown*       punkPin;
250
251         TRACE("(%p)->(%p)\n",This,ppenum);
252
253         if ( ppenum == NULL )
254                 return E_POINTER;
255         *ppenum = NULL;
256
257         pListPins = QUARTZ_CompList_Alloc();
258         if ( pListPins == NULL )
259                 return E_OUTOFMEMORY;
260
261         QUARTZ_CompList_Lock( This->pInPins );
262         QUARTZ_CompList_Lock( This->pOutPins );
263
264         pItem = QUARTZ_CompList_GetFirst( This->pInPins );
265         while ( pItem != NULL )
266         {
267                 punkPin = QUARTZ_CompList_GetItemPtr( pItem );
268                 hr = QUARTZ_CompList_AddComp( pListPins, punkPin, NULL, 0 );
269                 if ( FAILED(hr) )
270                         goto err;
271                 pItem = QUARTZ_CompList_GetNext( This->pInPins, pItem );
272         }
273
274         pItem = QUARTZ_CompList_GetFirst( This->pOutPins );
275         while ( pItem != NULL )
276         {
277                 punkPin = QUARTZ_CompList_GetItemPtr( pItem );
278                 hr = QUARTZ_CompList_AddComp( pListPins, punkPin, NULL, 0 );
279                 if ( FAILED(hr) )
280                         goto err;
281                 pItem = QUARTZ_CompList_GetNext( This->pOutPins, pItem );
282         }
283
284         hr = QUARTZ_CreateEnumUnknown(
285                 &IID_IEnumPins, (void**)ppenum, pListPins );
286 err:
287         QUARTZ_CompList_Unlock( This->pInPins );
288         QUARTZ_CompList_Unlock( This->pOutPins );
289
290         QUARTZ_CompList_Free( pListPins );
291
292         return hr;
293 }
294
295 static HRESULT WINAPI
296 CBaseFilterImpl_fnFindPin(IBaseFilter* iface,LPCWSTR lpwszId,IPin** ppobj)
297 {
298         ICOM_THIS(CBaseFilterImpl,iface);
299
300         FIXME("(%p)->(%s,%p) stub!\n",This,debugstr_w(lpwszId),ppobj);
301
302         if ( ppobj == NULL )
303                 return E_POINTER;
304
305
306
307         return E_NOTIMPL;
308 }
309
310 static HRESULT WINAPI
311 CBaseFilterImpl_fnQueryFilterInfo(IBaseFilter* iface,FILTER_INFO* pfi)
312 {
313         ICOM_THIS(CBaseFilterImpl,iface);
314
315         TRACE("(%p)->(%p)\n",This,pfi);
316
317         if ( pfi == NULL )
318                 return E_POINTER;
319
320         EnterCriticalSection( &This->csFilter );
321
322         if ( This->cbNameGraph <= sizeof(WCHAR)*MAX_FILTER_NAME )
323         {
324                 memcpy( pfi->achName, This->pwszNameGraph, This->cbNameGraph );
325         }
326         else
327         {
328                 memcpy( pfi->achName, This->pwszNameGraph,
329                                 sizeof(WCHAR)*MAX_FILTER_NAME );
330                 pfi->achName[MAX_FILTER_NAME-1] = (WCHAR)0;
331         }
332
333         pfi->pGraph = This->pfg;
334         if ( pfi->pGraph != NULL )
335                 IFilterGraph_AddRef(pfi->pGraph);
336
337         LeaveCriticalSection( &This->csFilter );
338
339         return NOERROR;
340 }
341
342 static HRESULT WINAPI
343 CBaseFilterImpl_fnJoinFilterGraph(IBaseFilter* iface,IFilterGraph* pfg,LPCWSTR lpwszName)
344 {
345         ICOM_THIS(CBaseFilterImpl,iface);
346         HRESULT hr;
347
348         TRACE("(%p)->(%p,%s)\n",This,pfg,debugstr_w(lpwszName));
349
350         EnterCriticalSection( &This->csFilter );
351
352         if ( This->pwszNameGraph != NULL )
353         {
354                 QUARTZ_FreeMem( This->pwszNameGraph );
355                 This->pwszNameGraph = NULL;
356                 This->cbNameGraph = 0;
357         }
358
359         This->pfg = pfg;
360         This->cbNameGraph = sizeof(WCHAR) * (lstrlenW(lpwszName)+1);
361         This->pwszNameGraph = (WCHAR*)QUARTZ_AllocMem( This->cbNameGraph );
362         if ( This->pwszNameGraph == NULL )
363         {
364                 hr = E_OUTOFMEMORY;
365                 goto err;
366         }
367         memcpy( This->pwszNameGraph, lpwszName, This->cbNameGraph );
368
369         hr = NOERROR;
370 err:
371         LeaveCriticalSection( &This->csFilter );
372
373         return hr;
374 }
375
376 static HRESULT WINAPI
377 CBaseFilterImpl_fnQueryVendorInfo(IBaseFilter* iface,LPWSTR* lpwszVendor)
378 {
379         ICOM_THIS(CBaseFilterImpl,iface);
380
381         TRACE("(%p)->(%p)\n",This,lpwszVendor);
382
383         /* E_NOTIMPL means 'no vender information'. */
384         return E_NOTIMPL;
385 }
386
387
388 /***************************************************************************
389  *
390  *      construct/destruct CBaseFilterImpl
391  *
392  */
393
394 static ICOM_VTABLE(IBaseFilter) ibasefilter =
395 {
396         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
397         /* IUnknown fields */
398         CBaseFilterImpl_fnQueryInterface,
399         CBaseFilterImpl_fnAddRef,
400         CBaseFilterImpl_fnRelease,
401         /* IPersist fields */
402         CBaseFilterImpl_fnGetClassID,
403         /* IMediaFilter fields */
404         CBaseFilterImpl_fnStop,
405         CBaseFilterImpl_fnPause,
406         CBaseFilterImpl_fnRun,
407         CBaseFilterImpl_fnGetState,
408         CBaseFilterImpl_fnSetSyncSource,
409         CBaseFilterImpl_fnGetSyncSource,
410         /* IBaseFilter fields */
411         CBaseFilterImpl_fnEnumPins,
412         CBaseFilterImpl_fnFindPin,
413         CBaseFilterImpl_fnQueryFilterInfo,
414         CBaseFilterImpl_fnJoinFilterGraph,
415         CBaseFilterImpl_fnQueryVendorInfo,
416 };
417
418
419 HRESULT CBaseFilterImpl_InitIBaseFilter(
420         CBaseFilterImpl* This, IUnknown* punkControl,
421         const CLSID* pclsidFilter, LPCWSTR lpwszNameGraph,
422         const CBaseFilterHandlers* pHandlers )
423 {
424         TRACE("(%p,%p)\n",This,punkControl);
425
426         if ( punkControl == NULL )
427         {
428                 ERR( "punkControl must not be NULL\n" );
429                 return E_INVALIDARG;
430         }
431
432         ICOM_VTBL(This) = &ibasefilter;
433         This->punkControl = punkControl;
434         This->pHandlers = pHandlers;
435         This->pclsidFilter = pclsidFilter;
436         This->pInPins = NULL;
437         This->pOutPins = NULL;
438         This->pfg = NULL;
439         This->cbNameGraph = 0;
440         This->pwszNameGraph = NULL;
441         This->pClock = NULL;
442         This->rtStart = 0;
443         This->fstate = State_Stopped;
444
445         This->cbNameGraph = sizeof(WCHAR) * (lstrlenW(lpwszNameGraph)+1);
446         This->pwszNameGraph = (WCHAR*)QUARTZ_AllocMem( This->cbNameGraph );
447         if ( This->pwszNameGraph == NULL )
448                 return E_OUTOFMEMORY;
449         memcpy( This->pwszNameGraph, lpwszNameGraph, This->cbNameGraph );
450
451         This->pInPins = QUARTZ_CompList_Alloc();
452         This->pOutPins = QUARTZ_CompList_Alloc();
453         if ( This->pInPins == NULL || This->pOutPins == NULL )
454         {
455                 if ( This->pInPins != NULL )
456                         QUARTZ_CompList_Free(This->pInPins);
457                 if ( This->pOutPins != NULL )
458                         QUARTZ_CompList_Free(This->pOutPins);
459                 QUARTZ_FreeMem(This->pwszNameGraph);
460                 return E_OUTOFMEMORY;
461         }
462
463         InitializeCriticalSection( &This->csFilter );
464
465         return NOERROR;
466 }
467
468 void CBaseFilterImpl_UninitIBaseFilter( CBaseFilterImpl* This )
469 {
470         QUARTZ_CompListItem*    pListItem;
471         IPin*   pPin;
472
473         TRACE("(%p)\n",This);
474
475         if ( This->pInPins != NULL )
476         {
477                 while ( 1 )
478                 {
479                         pListItem = QUARTZ_CompList_GetFirst( This->pInPins );
480                         if ( pListItem == NULL )
481                                 break;
482                         pPin = (IPin*)QUARTZ_CompList_GetItemPtr( pListItem );
483                         QUARTZ_CompList_RemoveComp( This->pInPins, (IUnknown*)pPin );
484                 }
485
486                 QUARTZ_CompList_Free( This->pInPins );
487                 This->pInPins = NULL;
488         }
489         if ( This->pOutPins != NULL )
490         {
491                 while ( 1 )
492                 {
493                         pListItem = QUARTZ_CompList_GetFirst( This->pOutPins );
494                         if ( pListItem == NULL )
495                                 break;
496                         pPin = (IPin*)QUARTZ_CompList_GetItemPtr( pListItem );
497                         QUARTZ_CompList_RemoveComp( This->pOutPins, (IUnknown*)pPin );
498                 }
499
500                 QUARTZ_CompList_Free( This->pOutPins );
501                 This->pOutPins = NULL;
502         }
503
504         if ( This->pwszNameGraph != NULL )
505         {
506                 QUARTZ_FreeMem( This->pwszNameGraph );
507                 This->pwszNameGraph = NULL;
508         }
509
510         if ( This->pClock != NULL )
511         {
512                 IReferenceClock_Release( This->pClock );
513                 This->pClock = NULL;
514         }
515
516         DeleteCriticalSection( &This->csFilter );
517 }
518
519 /***************************************************************************
520  *
521  *      CBaseFilterImpl methods
522  *
523  */
524
525 HRESULT CBaseFilterImpl_MediaEventNotify(
526         CBaseFilterImpl* This, long lEvent,LONG_PTR lParam1,LONG_PTR lParam2)
527 {
528         IMediaEventSink*        pSink = NULL;
529         HRESULT hr = E_NOTIMPL;
530
531         EnterCriticalSection( &This->csFilter );
532
533         if ( This->pfg == NULL )
534         {
535                 hr = E_UNEXPECTED;
536                 goto err;
537         }
538
539         hr = IFilterGraph_QueryInterface( This->pfg, &IID_IMediaEventSink, (void**)&pSink );
540         if ( FAILED(hr) )
541                 goto err;
542         if ( pSink == NULL )
543         {
544                 hr = E_FAIL;
545                 goto err;
546         }
547
548         hr = IMediaEventSink_Notify(pSink,lEvent,lParam1,lParam2);
549         IMediaEventSink_Release(pSink);
550 err:
551         LeaveCriticalSection( &This->csFilter );
552
553         return hr;
554 }
555