source: trunk/src/quartz/ifgraph.c@ 6710

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

wine update

File size: 13.8 KB
Line 
1/*
2 * Implementation of IFilterGraph.
3 *
4 * FIXME - stub.
5 * FIXME - implement IGraphBuilder / IFilterGraph2.
6 *
7 * hidenori@a2.ctktv.ne.jp
8 */
9
10#include "config.h"
11
12#include "windef.h"
13#include "winbase.h"
14#include "wingdi.h"
15#include "winerror.h"
16#include "wine/obj_base.h"
17#include "wine/obj_oleaut.h"
18#include "strmif.h"
19#include "control.h"
20#include "uuids.h"
21#include "vfwmsgs.h"
22#include "wine/unicode.h"
23
24#include "debugtools.h"
25DEFAULT_DEBUG_CHANNEL(quartz);
26
27#include "quartz_private.h"
28#include "fgraph.h"
29#include "enumunk.h"
30
31
32static HRESULT CFilterGraph_DisconnectAllPins( IBaseFilter* pFilter )
33{
34 IEnumPins* pEnum = NULL;
35 IPin* pPin;
36 IPin* pConnTo;
37 ULONG cFetched;
38 HRESULT hr;
39
40 hr = IBaseFilter_EnumPins( pFilter, &pEnum );
41 if ( FAILED(hr) )
42 return hr;
43 if ( pEnum == NULL )
44 return E_FAIL;
45
46 while ( 1 )
47 {
48 pPin = NULL;
49 cFetched = 0;
50 hr = IEnumPins_Next( pEnum, 1, &pPin, &cFetched );
51 if ( FAILED(hr) )
52 break;
53 if ( hr != NOERROR || pPin == NULL || cFetched != 1 )
54 {
55 hr = NOERROR;
56 break;
57 }
58
59 pConnTo = NULL;
60 hr = IPin_ConnectedTo(pPin,&pConnTo);
61 if ( hr == NOERROR && pConnTo != NULL )
62 {
63 IPin_Disconnect(pPin);
64 IPin_Disconnect(pConnTo);
65 IPin_Release(pConnTo);
66 }
67
68 IPin_Release( pPin );
69 }
70
71 IEnumPins_Release( pEnum );
72
73 return hr;
74}
75
76
77/****************************************************************************/
78
79static HRESULT WINAPI
80IFilterGraph2_fnQueryInterface(IFilterGraph2* iface,REFIID riid,void** ppobj)
81{
82 CFilterGraph_THIS(iface,fgraph);
83
84 TRACE("(%p)->()\n",This);
85
86 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
87}
88
89static ULONG WINAPI
90IFilterGraph2_fnAddRef(IFilterGraph2* iface)
91{
92 CFilterGraph_THIS(iface,fgraph);
93
94 TRACE("(%p)->()\n",This);
95
96 return IUnknown_AddRef(This->unk.punkControl);
97}
98
99static ULONG WINAPI
100IFilterGraph2_fnRelease(IFilterGraph2* iface)
101{
102 CFilterGraph_THIS(iface,fgraph);
103
104 TRACE("(%p)->()\n",This);
105
106 return IUnknown_Release(This->unk.punkControl);
107}
108
109static HRESULT WINAPI
110IFilterGraph2_fnAddFilter(IFilterGraph2* iface,IBaseFilter* pFilter, LPCWSTR pName)
111{
112 CFilterGraph_THIS(iface,fgraph);
113 FILTER_INFO info;
114 HRESULT hr;
115 HRESULT hrSucceeded = S_OK;
116 QUARTZ_CompListItem* pItem;
117 int i,iLen;
118
119 TRACE( "(%p)->(%p,%s)\n",This,pFilter,debugstr_w(pName) );
120
121 QUARTZ_CompList_Lock( This->m_pFilterList );
122
123 if ( pName != NULL )
124 {
125 pItem = QUARTZ_CompList_SearchData(
126 This->m_pFilterList,
127 pName, sizeof(WCHAR)*(strlenW(pName)+1) );
128 if ( pItem == NULL )
129 goto name_ok;
130
131 hrSucceeded = VFW_S_DUPLICATE_NAME;
132
133 iLen = strlenW(pName);
134 if ( iLen > 32 )
135 iLen = 32;
136 memcpy( info.achName, pName, sizeof(WCHAR)*iLen );
137 info.achName[iLen] = 0;
138 }
139 else
140 {
141 ZeroMemory( &info, sizeof(info) );
142 hr = IBaseFilter_QueryFilterInfo( pFilter, &info );
143 if ( FAILED(hr) )
144 goto end;
145
146 iLen = strlenW(info.achName);
147 pItem = QUARTZ_CompList_SearchData(
148 This->m_pFilterList,
149 info.achName, sizeof(WCHAR)*(iLen+1) );
150 if ( pItem == NULL )
151 {
152 pName = info.achName;
153 goto name_ok;
154 }
155 }
156
157 /* generate modified names for this filter.. */
158 iLen = strlenW(info.achName);
159 if ( iLen > 32 )
160 iLen = 32;
161 info.achName[iLen++] = ' ';
162
163 for ( i = 0; i <= 99; i++ )
164 {
165 info.achName[iLen+0] = (i%10) + '0';
166 info.achName[iLen+1] = ((i/10)%10) + '0';
167 info.achName[iLen+2] = 0;
168 pItem = QUARTZ_CompList_SearchData(
169 This->m_pFilterList,
170 info.achName, sizeof(WCHAR)*(iLen+3) );
171 if ( pItem == NULL )
172 {
173 pName = info.achName;
174 goto name_ok;
175 }
176 }
177
178 hr = ( pName == NULL ) ? E_FAIL : VFW_E_DUPLICATE_NAME;
179 goto end;
180
181name_ok:
182 /* register this filter. */
183 hr = QUARTZ_CompList_AddComp(
184 This->m_pFilterList, (IUnknown*)pFilter,
185 pName, sizeof(WCHAR)*(strlenW(pName)+1) );
186 if ( FAILED(hr) )
187 goto end;
188
189 hr = IBaseFilter_JoinFilterGraph(pFilter,(IFilterGraph*)iface,pName);
190 if ( FAILED(hr) )
191 {
192 QUARTZ_CompList_RemoveComp(
193 This->m_pFilterList,(IUnknown*)pFilter);
194 goto end;
195 }
196
197 EnterCriticalSection( &This->m_csGraphVersion );
198 This->m_lGraphVersion ++;
199 LeaveCriticalSection( &This->m_csGraphVersion );
200
201 hr = hrSucceeded;
202end:
203 QUARTZ_CompList_Unlock( This->m_pFilterList );
204
205 return hr;
206}
207
208static HRESULT WINAPI
209IFilterGraph2_fnRemoveFilter(IFilterGraph2* iface,IBaseFilter* pFilter)
210{
211 CFilterGraph_THIS(iface,fgraph);
212 QUARTZ_CompListItem* pItem;
213 HRESULT hr = NOERROR;
214
215 TRACE( "(%p)->(%p)\n",This,pFilter );
216
217 QUARTZ_CompList_Lock( This->m_pFilterList );
218
219 pItem = QUARTZ_CompList_SearchComp(
220 This->m_pFilterList, (IUnknown*)pFilter );
221 if ( pItem != NULL )
222 {
223 CFilterGraph_DisconnectAllPins(pFilter);
224 hr = IBaseFilter_JoinFilterGraph(
225 pFilter, NULL, QUARTZ_CompList_GetDataPtr(pItem) );
226 QUARTZ_CompList_RemoveComp(
227 This->m_pFilterList, (IUnknown*)pFilter );
228 }
229
230 EnterCriticalSection( &This->m_csGraphVersion );
231 This->m_lGraphVersion ++;
232 LeaveCriticalSection( &This->m_csGraphVersion );
233
234 QUARTZ_CompList_Unlock( This->m_pFilterList );
235
236 return hr;
237}
238
239static HRESULT WINAPI
240IFilterGraph2_fnEnumFilters(IFilterGraph2* iface,IEnumFilters** ppEnum)
241{
242 CFilterGraph_THIS(iface,fgraph);
243 HRESULT hr;
244
245 TRACE( "(%p)->(%p)\n",This,ppEnum );
246
247 QUARTZ_CompList_Lock( This->m_pFilterList );
248
249 hr = QUARTZ_CreateEnumUnknown(
250 &IID_IEnumFilters, (void**)ppEnum, This->m_pFilterList );
251
252 QUARTZ_CompList_Unlock( This->m_pFilterList );
253
254 return hr;
255}
256
257static HRESULT WINAPI
258IFilterGraph2_fnFindFilterByName(IFilterGraph2* iface,LPCWSTR pName,IBaseFilter** ppFilter)
259{
260 CFilterGraph_THIS(iface,fgraph);
261 QUARTZ_CompListItem* pItem;
262 HRESULT hr = E_FAIL;
263
264 TRACE( "(%p)->(%s,%p)\n",This,debugstr_w(pName),ppFilter );
265
266 if ( ppFilter == NULL )
267 return E_POINTER;
268 *ppFilter = NULL;
269
270 QUARTZ_CompList_Lock( This->m_pFilterList );
271
272 pItem = QUARTZ_CompList_SearchData(
273 This->m_pFilterList,
274 pName, sizeof(WCHAR)*(strlenW(pName)+1) );
275 if ( pItem != NULL )
276 {
277 *ppFilter = (IBaseFilter*)QUARTZ_CompList_GetItemPtr(pItem);
278 hr = NOERROR;
279 }
280
281 QUARTZ_CompList_Unlock( This->m_pFilterList );
282
283 return hr;
284}
285
286static HRESULT WINAPI
287IFilterGraph2_fnConnectDirect(IFilterGraph2* iface,IPin* pOut,IPin* pIn,const AM_MEDIA_TYPE* pmt)
288{
289 CFilterGraph_THIS(iface,fgraph);
290 IPin* pConnTo;
291 PIN_INFO infoIn;
292 PIN_INFO infoOut;
293 FILTER_INFO finfoIn;
294 FILTER_INFO finfoOut;
295 HRESULT hr;
296
297 TRACE( "(%p)->(%p,%p,%p)\n",This,pOut,pIn,pmt );
298
299 infoIn.pFilter = NULL;
300 infoOut.pFilter = NULL;
301 finfoIn.pGraph = NULL;
302 finfoOut.pGraph = NULL;
303
304 QUARTZ_CompList_Lock( This->m_pFilterList );
305
306 hr = IPin_QueryPinInfo(pIn,&infoIn);
307 if ( FAILED(hr) )
308 goto end;
309 hr = IPin_QueryPinInfo(pOut,&infoOut);
310 if ( FAILED(hr) )
311 goto end;
312 if ( infoIn.pFilter == NULL || infoOut.pFilter == NULL ||
313 infoIn.dir != PINDIR_INPUT || infoOut.dir != PINDIR_OUTPUT )
314 {
315 hr = E_FAIL;
316 goto end;
317 }
318
319 hr = IBaseFilter_QueryFilterInfo(infoIn.pFilter,&finfoIn);
320 if ( FAILED(hr) )
321 goto end;
322 hr = IBaseFilter_QueryFilterInfo(infoOut.pFilter,&finfoOut);
323 if ( FAILED(hr) )
324 goto end;
325 if ( finfoIn.pGraph != ((IFilterGraph*)iface) ||
326 finfoOut.pGraph != ((IFilterGraph*)iface) )
327 {
328 hr = E_FAIL;
329 goto end;
330 }
331
332 pConnTo = NULL;
333 hr = IPin_ConnectedTo(pIn,&pConnTo);
334 if ( FAILED(hr) )
335 goto end;
336 if ( pConnTo != NULL )
337 {
338 IPin_Release(pConnTo);
339 goto end;
340 }
341
342 pConnTo = NULL;
343 hr = IPin_ConnectedTo(pOut,&pConnTo);
344 if ( FAILED(hr) )
345 goto end;
346 if ( pConnTo != NULL )
347 {
348 IPin_Release(pConnTo);
349 goto end;
350 }
351
352 hr = IPin_Connect(pIn,pOut,pmt);
353 if ( FAILED(hr) )
354 goto end;
355 hr = IPin_Connect(pOut,pIn,pmt);
356 if ( FAILED(hr) )
357 {
358 IPin_Disconnect(pIn);
359 goto end;
360 }
361
362 EnterCriticalSection( &This->m_csGraphVersion );
363 This->m_lGraphVersion ++;
364 LeaveCriticalSection( &This->m_csGraphVersion );
365
366end:
367 QUARTZ_CompList_Unlock( This->m_pFilterList );
368
369 if ( infoIn.pFilter != NULL )
370 IBaseFilter_Release(infoIn.pFilter);
371 if ( infoOut.pFilter != NULL )
372 IBaseFilter_Release(infoOut.pFilter);
373 if ( finfoIn.pGraph != NULL )
374 IFilterGraph_Release(finfoIn.pGraph);
375 if ( finfoOut.pGraph != NULL )
376 IFilterGraph_Release(finfoOut.pGraph);
377
378 return hr;
379}
380
381static HRESULT WINAPI
382IFilterGraph2_fnReconnect(IFilterGraph2* iface,IPin* pPin)
383{
384 CFilterGraph_THIS(iface,fgraph);
385
386 FIXME( "(%p)->(%p) stub!\n",This,pPin );
387
388 EnterCriticalSection( &This->m_csGraphVersion );
389 This->m_lGraphVersion ++;
390 LeaveCriticalSection( &This->m_csGraphVersion );
391
392 return E_NOTIMPL;
393}
394
395static HRESULT WINAPI
396IFilterGraph2_fnDisconnect(IFilterGraph2* iface,IPin* pPin)
397{
398 CFilterGraph_THIS(iface,fgraph);
399
400 FIXME( "(%p)->(%p) stub!\n",This,pPin );
401
402 EnterCriticalSection( &This->m_csGraphVersion );
403 This->m_lGraphVersion ++;
404 LeaveCriticalSection( &This->m_csGraphVersion );
405
406 return E_NOTIMPL;
407}
408
409static HRESULT WINAPI
410IFilterGraph2_fnSetDefaultSyncSource(IFilterGraph2* iface)
411{
412 CFilterGraph_THIS(iface,fgraph);
413
414 FIXME( "(%p)->() stub!\n", This );
415 return E_NOTIMPL;
416}
417
418static HRESULT WINAPI
419IFilterGraph2_fnConnect(IFilterGraph2* iface,IPin* pOut,IPin* pIn)
420{
421 CFilterGraph_THIS(iface,fgraph);
422 HRESULT hr;
423
424 TRACE( "(%p)->(%p,%p)\n",This,pOut,pIn );
425
426 /* At first, try to connect directly. */
427 hr = IFilterGraph_ConnectDirect(iface,pOut,pIn,NULL);
428 if ( hr == NOERROR )
429 return NOERROR;
430
431 /* FIXME - try to connect indirectly. */
432 FIXME( "(%p)->(%p,%p) stub!\n",This,pOut,pIn );
433
434
435 return E_NOTIMPL;
436}
437
438static HRESULT WINAPI
439IFilterGraph2_fnRender(IFilterGraph2* iface,IPin* pOut)
440{
441 CFilterGraph_THIS(iface,fgraph);
442
443 FIXME( "(%p)->(%p) stub!\n",This,pOut );
444 return E_NOTIMPL;
445}
446
447static HRESULT WINAPI
448IFilterGraph2_fnRenderFile(IFilterGraph2* iface,LPCWSTR lpFileName,LPCWSTR lpPlayList)
449{
450 CFilterGraph_THIS(iface,fgraph);
451 HRESULT hr;
452 IBaseFilter* pFilter = NULL;
453 IEnumPins* pEnum = NULL;
454 IPin* pPin;
455 ULONG cFetched;
456 PIN_DIRECTION dir;
457 ULONG cTryToRender;
458 ULONG cActRender;
459
460 TRACE( "(%p)->(%s,%s)\n",This,
461 debugstr_w(lpFileName),debugstr_w(lpPlayList) );
462
463 if ( lpPlayList != NULL )
464 return E_INVALIDARG;
465
466 pFilter = NULL;
467 hr = IFilterGraph2_AddSourceFilter(iface,lpFileName,NULL,&pFilter);
468 if ( FAILED(hr) )
469 goto end;
470 if ( pFilter == NULL )
471 {
472 hr = E_FAIL;
473 goto end;
474 }
475 pEnum = NULL;
476 hr = IBaseFilter_EnumPins( pFilter, &pEnum );
477 if ( FAILED(hr) )
478 goto end;
479 if ( pEnum == NULL )
480 {
481 hr = E_FAIL;
482 goto end;
483 }
484
485 cTryToRender = 0;
486 cActRender = 0;
487
488 while ( 1 )
489 {
490 pPin = NULL;
491 cFetched = 0;
492 hr = IEnumPins_Next( pEnum, 1, &pPin, &cFetched );
493 if ( FAILED(hr) )
494 goto end;
495 if ( hr != NOERROR || pPin == NULL || cFetched != 1 )
496 {
497 hr = NOERROR;
498 break;
499 }
500 hr = IPin_QueryDirection( pPin, &dir );
501 if ( hr == NOERROR && dir == PINDIR_OUTPUT )
502 {
503 cTryToRender ++;
504 hr = IFilterGraph2_Render( iface, pPin );
505 if ( hr == NOERROR )
506 cActRender ++;
507 }
508 IPin_Release( pPin );
509 }
510
511 if ( hr == NOERROR )
512 {
513 if ( cTryToRender > cActRender )
514 hr = VFW_S_PARTIAL_RENDER;
515 if ( cActRender == 0 )
516 hr = E_FAIL;
517 }
518
519end:
520 if ( pEnum != NULL )
521 IEnumPins_Release( pEnum );
522 if ( pFilter != NULL )
523 IBaseFilter_Release( pFilter );
524
525 return hr;
526}
527
528static HRESULT WINAPI
529IFilterGraph2_fnAddSourceFilter(IFilterGraph2* iface,LPCWSTR lpFileName,LPCWSTR lpFilterName,IBaseFilter** ppBaseFilter)
530{
531 CFilterGraph_THIS(iface,fgraph);
532
533 FIXME( "(%p)->(%s,%s,%p) stub!\n",This,
534 debugstr_w(lpFileName),debugstr_w(lpFilterName),ppBaseFilter );
535 return E_NOTIMPL;
536}
537
538static HRESULT WINAPI
539IFilterGraph2_fnSetLogFile(IFilterGraph2* iface,DWORD_PTR hFile)
540{
541 CFilterGraph_THIS(iface,fgraph);
542
543 FIXME( "(%p)->() stub!\n", This );
544 return E_NOTIMPL;
545}
546
547static HRESULT WINAPI
548IFilterGraph2_fnAbort(IFilterGraph2* iface)
549{
550 CFilterGraph_THIS(iface,fgraph);
551
552 /* undoc. */
553
554 FIXME( "(%p)->() stub!\n", This );
555 return E_NOTIMPL;
556}
557
558static HRESULT WINAPI
559IFilterGraph2_fnShouldOperationContinue(IFilterGraph2* iface)
560{
561 CFilterGraph_THIS(iface,fgraph);
562
563 /* undoc. */
564
565 FIXME( "(%p)->() stub!\n", This );
566 return E_NOTIMPL;
567}
568
569static HRESULT WINAPI
570IFilterGraph2_fnAddSourceFilterForMoniker(IFilterGraph2* iface,IMoniker* pMon,IBindCtx* pCtx,LPCWSTR pFilterName,IBaseFilter** ppFilter)
571{
572 CFilterGraph_THIS(iface,fgraph);
573
574 FIXME( "(%p)->() stub!\n", This );
575 return E_NOTIMPL;
576}
577
578static HRESULT WINAPI
579IFilterGraph2_fnReconnectEx(IFilterGraph2* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
580{
581 CFilterGraph_THIS(iface,fgraph);
582
583 FIXME( "(%p)->(%p,%p) stub!\n",This,pPin,pmt );
584
585 EnterCriticalSection( &This->m_csGraphVersion );
586 This->m_lGraphVersion ++;
587 LeaveCriticalSection( &This->m_csGraphVersion );
588
589 return E_NOTIMPL;
590}
591
592static HRESULT WINAPI
593IFilterGraph2_fnRenderEx(IFilterGraph2* iface,IPin* pPin,DWORD dwParam1,DWORD* pdwParam2)
594{
595 CFilterGraph_THIS(iface,fgraph);
596
597 /* undoc. */
598 FIXME( "(%p)->(%p,%08lx,%p) stub!\n",This,pPin,dwParam1,pdwParam2);
599 return E_NOTIMPL;
600}
601
602
603
604
605static ICOM_VTABLE(IFilterGraph2) ifgraph =
606{
607 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
608 /* IUnknown fields */
609 IFilterGraph2_fnQueryInterface,
610 IFilterGraph2_fnAddRef,
611 IFilterGraph2_fnRelease,
612 /* IFilterGraph fields */
613 IFilterGraph2_fnAddFilter,
614 IFilterGraph2_fnRemoveFilter,
615 IFilterGraph2_fnEnumFilters,
616 IFilterGraph2_fnFindFilterByName,
617 IFilterGraph2_fnConnectDirect,
618 IFilterGraph2_fnReconnect,
619 IFilterGraph2_fnDisconnect,
620 IFilterGraph2_fnSetDefaultSyncSource,
621 /* IGraphBuilder fields */
622 IFilterGraph2_fnConnect,
623 IFilterGraph2_fnRender,
624 IFilterGraph2_fnRenderFile,
625 IFilterGraph2_fnAddSourceFilter,
626 IFilterGraph2_fnSetLogFile,
627 IFilterGraph2_fnAbort,
628 IFilterGraph2_fnShouldOperationContinue,
629 /* IFilterGraph2 fields */
630 IFilterGraph2_fnAddSourceFilterForMoniker,
631 IFilterGraph2_fnReconnectEx,
632 IFilterGraph2_fnRenderEx,
633};
634
635HRESULT CFilterGraph_InitIFilterGraph2( CFilterGraph* pfg )
636{
637 TRACE("(%p)\n",pfg);
638 ICOM_VTBL(&pfg->fgraph) = &ifgraph;
639
640 pfg->m_pFilterList = QUARTZ_CompList_Alloc();
641 if ( pfg->m_pFilterList == NULL )
642 return E_OUTOFMEMORY;
643
644 return NOERROR;
645}
646
647void CFilterGraph_UninitIFilterGraph2( CFilterGraph* pfg )
648{
649 QUARTZ_CompListItem* pItem;
650
651 TRACE("(%p)\n",pfg);
652
653 /* remove all filters... */
654 while ( 1 )
655 {
656 pItem = QUARTZ_CompList_GetFirst( pfg->m_pFilterList );
657 if ( pItem == NULL )
658 break;
659 IFilterGraph2_fnRemoveFilter(
660 (IFilterGraph2*)(&pfg->fgraph),
661 (IBaseFilter*)QUARTZ_CompList_GetItemPtr(pItem) );
662 }
663
664 QUARTZ_CompList_Free( pfg->m_pFilterList );
665}
Note: See TracBrowser for help on using the repository browser.