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