Add $X_LIBS path while searching for libfreetype.
[wine/gsoc_dplay.git] / dlls / quartz / basepin.c
blob81bdb7653c9303885dd96a248a40902c3f6b4502
1 /*
2 * Implements IPin and IMemInputPin. (internal)
4 * hidenori@a2.ctktv.ne.jp
5 */
7 #include "config.h"
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"
17 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(quartz);
20 #include "quartz_private.h"
21 #include "basefilt.h"
22 #include "memalloc.h"
25 /***************************************************************************
27 * CPinBaseImpl
31 static HRESULT WINAPI
32 CPinBaseImpl_fnQueryInterface(IPin* iface,REFIID riid,void** ppobj)
34 ICOM_THIS(CPinBaseImpl,iface);
36 TRACE("(%p)->()\n",This);
38 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
41 static ULONG WINAPI
42 CPinBaseImpl_fnAddRef(IPin* iface)
44 ICOM_THIS(CPinBaseImpl,iface);
46 TRACE("(%p)->()\n",This);
48 return IUnknown_AddRef(This->punkControl);
51 static ULONG WINAPI
52 CPinBaseImpl_fnRelease(IPin* iface)
54 ICOM_THIS(CPinBaseImpl,iface);
56 TRACE("(%p)->()\n",This);
58 return IUnknown_Release(This->punkControl);
61 static HRESULT WINAPI
62 CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
64 ICOM_THIS(CPinBaseImpl,iface);
65 HRESULT hr = E_NOTIMPL;
66 ULONG i;
67 FILTER_STATE fs;
69 TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
71 if ( !This->bOutput )
73 TRACE("Connect() should not be sent to input pins\n");
74 return E_UNEXPECTED;
76 if ( pPin == NULL )
77 return E_POINTER;
79 TRACE("try to connect to %p\n",pPin);
81 EnterCriticalSection( This->pcsPin );
83 if ( This->pPinConnectedTo != NULL )
85 hr = VFW_E_ALREADY_CONNECTED;
86 goto err;
89 /* return fail if running */
90 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
91 if ( hr != S_OK || fs != State_Stopped )
93 TRACE("not stopped\n");
94 hr = VFW_E_NOT_STOPPED;
95 goto err;
98 if ( This->pHandlers->pOnPreConnect != NULL )
100 hr = This->pHandlers->pOnPreConnect(This,pPin);
101 if ( FAILED(hr) )
103 TRACE("OnPreconnect() failed hr = %08lx\n",hr);
104 goto err;
108 if ( pmt != NULL )
110 hr = IPin_QueryAccept(iface,pmt);
111 if ( FAILED(hr) )
112 goto err;
113 hr = IPin_ReceiveConnection(pPin,iface,pmt);
114 if ( FAILED(hr) )
115 goto err;
117 else
119 for ( i = 0; i < This->cAcceptTypes; i++ )
121 pmt = &This->pmtAcceptTypes[i];
122 hr = IPin_QueryAccept(iface,pmt);
123 if ( SUCCEEDED(hr) )
125 hr = IPin_ReceiveConnection(pPin,iface,pmt);
126 TRACE("ReceiveConnection - %08lx\n",hr);
127 if ( SUCCEEDED(hr) )
129 goto connected;
134 hr = VFW_E_TYPE_NOT_ACCEPTED;
135 goto err;
138 connected:;
139 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
140 if ( This->pmtConn == NULL )
142 hr = E_OUTOFMEMORY;
143 IPin_Disconnect(pPin);
144 goto err;
147 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
148 hr = IPin_QueryInterface(pPin,&IID_IMemInputPin,(void**)&This->pMemInputPinConnectedTo);
149 if ( FAILED(hr) )
151 TRACE("no IMemInputPin\n");
152 IPin_Disconnect(pPin);
153 goto err;
156 if ( This->pHandlers->pOnPostConnect != NULL )
158 hr = This->pHandlers->pOnPostConnect(This,pPin);
159 if ( FAILED(hr) )
161 TRACE("OnPostConnect() failed hr = %08lx\n",hr);
162 IPin_Disconnect(pPin);
163 goto err;
167 hr = S_OK;
169 err:
170 if ( FAILED(hr) )
172 IPin_Disconnect(iface);
174 LeaveCriticalSection( This->pcsPin );
176 TRACE("return %08lx\n",hr);
178 return hr;
181 static HRESULT WINAPI
182 CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
184 ICOM_THIS(CPinBaseImpl,iface);
185 HRESULT hr = E_NOTIMPL;
186 FILTER_STATE fs;
188 TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
190 if ( This->bOutput )
192 TRACE("ReceiveConnection() should not be sent to output pins\n");
193 return E_UNEXPECTED;
195 if ( pPin == NULL || pmt == NULL )
196 return E_POINTER;
198 EnterCriticalSection( This->pcsPin );
200 if ( This->pPinConnectedTo != NULL )
202 hr = VFW_E_ALREADY_CONNECTED;
203 goto err;
206 /* return fail if running */
207 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
208 if ( hr != S_OK || fs != State_Stopped )
210 TRACE("not stopped\n");
211 hr = VFW_E_NOT_STOPPED;
212 goto err;
215 if ( This->pHandlers->pOnPreConnect != NULL )
217 hr = This->pHandlers->pOnPreConnect(This,pPin);
218 if ( FAILED(hr) )
220 TRACE("OnPreConnect() failed hr = %08lx\n",hr);
221 goto err;
225 hr = IPin_QueryAccept(iface,pmt);
226 if ( FAILED(hr) )
227 goto err;
229 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
230 if ( This->pmtConn == NULL )
232 hr = E_OUTOFMEMORY;
233 goto err;
236 if ( This->pHandlers->pOnPostConnect != NULL )
238 hr = This->pHandlers->pOnPostConnect(This,pPin);
239 if ( FAILED(hr) )
241 TRACE("OnPostConnect() failed hr = %08lx\n",hr);
242 goto err;
246 hr = S_OK;
247 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
249 err:
250 if ( FAILED(hr) )
251 IPin_Disconnect(iface);
252 LeaveCriticalSection( This->pcsPin );
254 return hr;
257 static HRESULT WINAPI
258 CPinBaseImpl_fnDisconnect(IPin* iface)
260 ICOM_THIS(CPinBaseImpl,iface);
261 HRESULT hr = NOERROR;
262 FILTER_STATE fs;
264 TRACE("(%p)->()\n",This);
266 EnterCriticalSection( This->pcsPin );
268 /* return fail if running */
269 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
270 if ( hr != S_OK || fs != State_Stopped )
272 TRACE("not stopped\n");
273 hr = VFW_E_NOT_STOPPED;
274 goto err;
277 if ( This->pHandlers->pOnDisconnect != NULL )
278 hr = This->pHandlers->pOnDisconnect(This);
280 if ( This->pmtConn != NULL )
282 QUARTZ_MediaType_Destroy( This->pmtConn );
283 This->pmtConn = NULL;
285 if ( This->pMemInputPinConnectedTo != NULL )
287 IMemInputPin_Release(This->pMemInputPinConnectedTo);
288 This->pMemInputPinConnectedTo = NULL;
290 if ( This->pPinConnectedTo != NULL )
292 /* FIXME - cleanup */
294 IPin_Release(This->pPinConnectedTo);
295 This->pPinConnectedTo = NULL;
296 hr = NOERROR;
298 else
300 hr = S_FALSE; /* FIXME - is this correct??? */
303 err:
304 LeaveCriticalSection( This->pcsPin );
306 return hr;
309 static HRESULT WINAPI
310 CPinBaseImpl_fnConnectedTo(IPin* iface,IPin** ppPin)
312 ICOM_THIS(CPinBaseImpl,iface);
313 HRESULT hr = VFW_E_NOT_CONNECTED;
315 TRACE("(%p)->(%p)\n",This,ppPin);
317 if ( ppPin == NULL )
318 return E_POINTER;
320 EnterCriticalSection( This->pcsPin );
322 *ppPin = This->pPinConnectedTo;
323 if ( This->pPinConnectedTo != NULL )
325 IPin_AddRef(This->pPinConnectedTo);
326 hr = NOERROR;
329 LeaveCriticalSection( This->pcsPin );
331 return hr;
334 static HRESULT WINAPI
335 CPinBaseImpl_fnConnectionMediaType(IPin* iface,AM_MEDIA_TYPE* pmt)
337 ICOM_THIS(CPinBaseImpl,iface);
338 HRESULT hr = E_FAIL;
340 TRACE("(%p)->(%p)\n",This,pmt);
342 if ( pmt == NULL )
343 return E_POINTER;
345 EnterCriticalSection( This->pcsPin );
347 if ( This->pmtConn != NULL )
349 hr = QUARTZ_MediaType_Copy( pmt, This->pmtConn );
351 else
353 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
354 pmt->bFixedSizeSamples = TRUE;
355 pmt->lSampleSize = 1;
356 hr = VFW_E_NOT_CONNECTED;
359 LeaveCriticalSection( This->pcsPin );
361 return hr;
364 static HRESULT WINAPI
365 CPinBaseImpl_fnQueryPinInfo(IPin* iface,PIN_INFO* pinfo)
367 ICOM_THIS(CPinBaseImpl,iface);
369 TRACE("(%p)->(%p)\n",This,pinfo);
371 if ( pinfo == NULL )
372 return E_POINTER;
374 EnterCriticalSection( This->pcsPin );
376 ZeroMemory( pinfo, sizeof(PIN_INFO) );
377 pinfo->pFilter = (IBaseFilter*)(This->pFilter);
378 if ( pinfo->pFilter != NULL )
379 IBaseFilter_AddRef( pinfo->pFilter );
380 pinfo->dir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
381 if ( This->cbIdLen <= sizeof(pinfo->achName) )
382 memcpy( pinfo->achName, This->pwszId, This->cbIdLen );
383 else
385 memcpy( pinfo->achName, This->pwszId, sizeof(pinfo->achName) );
386 pinfo->achName[sizeof(pinfo->achName)/sizeof(pinfo->achName[0])-1] = 0;
389 LeaveCriticalSection( This->pcsPin );
391 return NOERROR;
394 static HRESULT WINAPI
395 CPinBaseImpl_fnQueryDirection(IPin* iface,PIN_DIRECTION* pdir)
397 ICOM_THIS(CPinBaseImpl,iface);
399 TRACE("(%p)->(%p)\n",This,pdir);
401 if ( pdir == NULL )
402 return E_POINTER;
404 *pdir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
406 return NOERROR;
409 static HRESULT WINAPI
410 CPinBaseImpl_fnQueryId(IPin* iface,LPWSTR* lpwszId)
412 ICOM_THIS(CPinBaseImpl,iface);
414 TRACE("(%p)->(%p)\n",This,lpwszId);
416 if ( lpwszId == NULL )
417 return E_POINTER;
419 *lpwszId = (WCHAR*)CoTaskMemAlloc( This->cbIdLen );
420 if ( *lpwszId == NULL )
421 return E_OUTOFMEMORY;
422 memcpy( *lpwszId, This->pwszId, This->cbIdLen );
424 return NOERROR;
427 static HRESULT WINAPI
428 CPinBaseImpl_fnQueryAccept(IPin* iface,const AM_MEDIA_TYPE* pmt)
430 ICOM_THIS(CPinBaseImpl,iface);
431 HRESULT hr;
433 TRACE("(%p)->(%p)\n",This,pmt);
435 if ( pmt == NULL )
436 return E_POINTER;
438 hr = NOERROR;
439 EnterCriticalSection( This->pcsPin );
440 if ( This->pHandlers->pCheckMediaType != NULL )
441 hr = This->pHandlers->pCheckMediaType(This,pmt);
442 LeaveCriticalSection( This->pcsPin );
444 return hr;
447 static HRESULT WINAPI
448 CPinBaseImpl_fnEnumMediaTypes(IPin* iface,IEnumMediaTypes** ppenum)
450 ICOM_THIS(CPinBaseImpl,iface);
451 HRESULT hr;
453 TRACE("(%p)->(%p)\n",This,ppenum);
455 if ( ppenum == NULL )
456 return E_POINTER;
458 hr = E_NOTIMPL;
460 EnterCriticalSection( This->pcsPin );
461 if ( This->cAcceptTypes > 0 )
462 hr = QUARTZ_CreateEnumMediaTypes(
463 ppenum, This->pmtAcceptTypes, This->cAcceptTypes );
464 LeaveCriticalSection( This->pcsPin );
466 return hr;
469 static HRESULT WINAPI
470 CPinBaseImpl_fnQueryInternalConnections(IPin* iface,IPin** ppPin,ULONG* pul)
472 ICOM_THIS(CPinBaseImpl,iface);
474 TRACE("(%p)->(%p,%p)\n",This,ppPin,pul);
476 /* E_NOTIMPL means 'no internal connections'. */
477 return E_NOTIMPL;
480 static HRESULT WINAPI
481 CPinBaseImpl_fnEndOfStream(IPin* iface)
483 ICOM_THIS(CPinBaseImpl,iface);
484 HRESULT hr = E_NOTIMPL;
486 TRACE("(%p)->()\n",This);
488 if ( This->bOutput )
489 return E_UNEXPECTED;
491 EnterCriticalSection( This->pcsPin );
492 if ( This->pHandlers->pEndOfStream != NULL )
493 hr = This->pHandlers->pEndOfStream(This);
494 LeaveCriticalSection( This->pcsPin );
496 return hr;
499 static HRESULT WINAPI
500 CPinBaseImpl_fnBeginFlush(IPin* iface)
502 ICOM_THIS(CPinBaseImpl,iface);
503 HRESULT hr = E_NOTIMPL;
505 TRACE("(%p)->()\n",This);
507 if ( This->bOutput )
508 return E_UNEXPECTED;
510 EnterCriticalSection( This->pcsPin );
511 if ( This->pHandlers->pBeginFlush != NULL )
512 hr = This->pHandlers->pBeginFlush(This);
513 LeaveCriticalSection( This->pcsPin );
515 return hr;
518 static HRESULT WINAPI
519 CPinBaseImpl_fnEndFlush(IPin* iface)
521 ICOM_THIS(CPinBaseImpl,iface);
522 HRESULT hr = E_NOTIMPL;
524 TRACE("(%p)->()\n",This);
526 if ( This->bOutput )
527 return E_UNEXPECTED;
529 EnterCriticalSection( This->pcsPin );
530 if ( This->pHandlers->pEndFlush != NULL )
531 hr = This->pHandlers->pEndFlush(This);
532 LeaveCriticalSection( This->pcsPin );
534 return hr;
537 static HRESULT WINAPI
538 CPinBaseImpl_fnNewSegment(IPin* iface,REFERENCE_TIME rtStart,REFERENCE_TIME rtStop,double rate)
540 ICOM_THIS(CPinBaseImpl,iface);
541 HRESULT hr = E_NOTIMPL;
543 TRACE("(%p)->()\n",This);
545 if ( This->bOutput )
546 return E_UNEXPECTED;
548 EnterCriticalSection( This->pcsPin );
549 if ( This->pHandlers->pNewSegment != NULL )
550 hr = This->pHandlers->pNewSegment(This,rtStart,rtStop,rate);
551 LeaveCriticalSection( This->pcsPin );
553 return hr;
559 static ICOM_VTABLE(IPin) ipin =
561 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
562 /* IUnknown fields */
563 CPinBaseImpl_fnQueryInterface,
564 CPinBaseImpl_fnAddRef,
565 CPinBaseImpl_fnRelease,
566 /* IPin fields */
567 CPinBaseImpl_fnConnect,
568 CPinBaseImpl_fnReceiveConnection,
569 CPinBaseImpl_fnDisconnect,
570 CPinBaseImpl_fnConnectedTo,
571 CPinBaseImpl_fnConnectionMediaType,
572 CPinBaseImpl_fnQueryPinInfo,
573 CPinBaseImpl_fnQueryDirection,
574 CPinBaseImpl_fnQueryId,
575 CPinBaseImpl_fnQueryAccept,
576 CPinBaseImpl_fnEnumMediaTypes,
577 CPinBaseImpl_fnQueryInternalConnections,
578 CPinBaseImpl_fnEndOfStream,
579 CPinBaseImpl_fnBeginFlush,
580 CPinBaseImpl_fnEndFlush,
581 CPinBaseImpl_fnNewSegment,
585 HRESULT CPinBaseImpl_InitIPin(
586 CPinBaseImpl* This, IUnknown* punkControl,
587 CRITICAL_SECTION* pcsPin,
588 CBaseFilterImpl* pFilter, LPCWSTR pwszId,
589 BOOL bOutput,
590 const CBasePinHandlers* pHandlers )
592 HRESULT hr = NOERROR;
594 TRACE("(%p,%p,%p)\n",This,punkControl,pFilter);
596 if ( punkControl == NULL )
598 ERR( "punkControl must not be NULL\n" );
599 return E_INVALIDARG;
602 ICOM_VTBL(This) = &ipin;
603 This->punkControl = punkControl;
604 This->pHandlers = pHandlers;
605 This->cbIdLen = sizeof(WCHAR)*(lstrlenW(pwszId)+1);
606 This->pwszId = NULL;
607 This->bOutput = bOutput;
608 This->pmtAcceptTypes = NULL;
609 This->cAcceptTypes = 0;
610 This->pcsPin = pcsPin;
611 This->pFilter = pFilter;
612 This->pPinConnectedTo = NULL;
613 This->pMemInputPinConnectedTo = NULL;
614 This->pmtConn = NULL;
615 This->pAsyncOut = NULL;
617 This->pwszId = (WCHAR*)QUARTZ_AllocMem( This->cbIdLen );
618 if ( This->pwszId == NULL )
620 hr = E_OUTOFMEMORY;
621 goto err;
623 memcpy( This->pwszId, pwszId, This->cbIdLen );
625 return NOERROR;
627 err:;
628 CPinBaseImpl_UninitIPin( This );
629 return hr;
632 void CPinBaseImpl_UninitIPin( CPinBaseImpl* This )
634 TRACE("(%p)\n",This);
636 IPin_Disconnect( (IPin*)(This) );
638 if ( This->pwszId != NULL )
640 QUARTZ_FreeMem( This->pwszId );
641 This->pwszId = NULL;
646 /***************************************************************************
648 * CMemInputPinBaseImpl
653 static HRESULT WINAPI
654 CMemInputPinBaseImpl_fnQueryInterface(IMemInputPin* iface,REFIID riid,void** ppobj)
656 ICOM_THIS(CMemInputPinBaseImpl,iface);
658 TRACE("(%p)->()\n",This);
660 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
663 static ULONG WINAPI
664 CMemInputPinBaseImpl_fnAddRef(IMemInputPin* iface)
666 ICOM_THIS(CMemInputPinBaseImpl,iface);
668 TRACE("(%p)->()\n",This);
670 return IUnknown_AddRef(This->punkControl);
673 static ULONG WINAPI
674 CMemInputPinBaseImpl_fnRelease(IMemInputPin* iface)
676 ICOM_THIS(CMemInputPinBaseImpl,iface);
678 TRACE("(%p)->()\n",This);
680 return IUnknown_Release(This->punkControl);
684 static HRESULT WINAPI
685 CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin* iface,IMemAllocator** ppAllocator)
687 ICOM_THIS(CMemInputPinBaseImpl,iface);
688 HRESULT hr = NOERROR;
689 IUnknown* punk;
691 TRACE("(%p)->()\n",This);
693 if ( ppAllocator == NULL )
694 return E_POINTER;
696 EnterCriticalSection( This->pPin->pcsPin );
698 if ( This->pAllocator == NULL )
700 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
701 if ( hr == NOERROR )
703 hr = IUnknown_QueryInterface(punk,
704 &IID_IMemAllocator,(void**)&This->pAllocator);
705 IUnknown_Release(punk);
709 if ( hr == NOERROR )
711 *ppAllocator = This->pAllocator;
712 IMemAllocator_AddRef(This->pAllocator);
715 LeaveCriticalSection( This->pPin->pcsPin );
717 return hr;
720 static HRESULT WINAPI
721 CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin* iface,IMemAllocator* pAllocator,BOOL bReadonly)
723 ICOM_THIS(CMemInputPinBaseImpl,iface);
725 TRACE("(%p)->()\n",This);
727 if ( pAllocator == NULL )
728 return E_POINTER;
730 EnterCriticalSection( This->pPin->pcsPin );
732 if ( This->pAllocator != NULL )
734 IMemAllocator_Release(This->pAllocator);
735 This->pAllocator = NULL;
737 This->pAllocator = pAllocator;
738 IMemAllocator_AddRef(This->pAllocator);
740 This->bReadonly = bReadonly;
742 LeaveCriticalSection( This->pPin->pcsPin );
744 return NOERROR;
747 static HRESULT WINAPI
748 CMemInputPinBaseImpl_fnGetAllocatorRequirements(IMemInputPin* iface,ALLOCATOR_PROPERTIES* pProp)
750 ICOM_THIS(CMemInputPinBaseImpl,iface);
752 TRACE("(%p)->(%p)\n",This,pProp);
754 if ( pProp == NULL )
755 return E_POINTER;
757 /* E_MOTIMPL means 'no requirements' */
758 return E_NOTIMPL;
761 static HRESULT WINAPI
762 CMemInputPinBaseImpl_fnReceive(IMemInputPin* iface,IMediaSample* pSample)
764 ICOM_THIS(CMemInputPinBaseImpl,iface);
765 HRESULT hr = E_NOTIMPL;
767 TRACE("(%p)->(%p)\n",This,pSample);
769 EnterCriticalSection( This->pPin->pcsPin );
770 if ( This->pPin->pHandlers->pReceive != NULL )
771 hr = This->pPin->pHandlers->pReceive(This->pPin,pSample);
772 LeaveCriticalSection( This->pPin->pcsPin );
774 return hr;
777 static HRESULT WINAPI
778 CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSample,long nSample,long* pnSampleProcessed)
780 ICOM_THIS(CMemInputPinBaseImpl,iface);
781 long n;
782 HRESULT hr;
784 TRACE("(%p)->()\n",This);
786 if ( ppSample == NULL || pnSampleProcessed == NULL )
787 return E_POINTER;
789 hr = NOERROR;
790 for ( n = 0; n < nSample; n++ )
792 hr = IMemInputPin_Receive(iface,ppSample[n]);
793 if ( FAILED(hr) )
794 break;
797 *pnSampleProcessed = n;
798 return hr;
801 static HRESULT WINAPI
802 CMemInputPinBaseImpl_fnReceiveCanBlock(IMemInputPin* iface)
804 ICOM_THIS(CMemInputPinBaseImpl,iface);
805 HRESULT hr = E_NOTIMPL;
807 TRACE("(%p)->()\n",This);
809 EnterCriticalSection( This->pPin->pcsPin );
810 if ( This->pPin->pHandlers->pReceiveCanBlock != NULL )
811 hr = This->pPin->pHandlers->pReceiveCanBlock(This->pPin);
812 LeaveCriticalSection( This->pPin->pcsPin );
814 return hr;
818 static ICOM_VTABLE(IMemInputPin) imeminputpin =
820 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
821 /* IUnknown fields */
822 CMemInputPinBaseImpl_fnQueryInterface,
823 CMemInputPinBaseImpl_fnAddRef,
824 CMemInputPinBaseImpl_fnRelease,
825 /* IMemInputPin fields */
826 CMemInputPinBaseImpl_fnGetAllocator,
827 CMemInputPinBaseImpl_fnNotifyAllocator,
828 CMemInputPinBaseImpl_fnGetAllocatorRequirements,
829 CMemInputPinBaseImpl_fnReceive,
830 CMemInputPinBaseImpl_fnReceiveMultiple,
831 CMemInputPinBaseImpl_fnReceiveCanBlock,
834 HRESULT CMemInputPinBaseImpl_InitIMemInputPin(
835 CMemInputPinBaseImpl* This, IUnknown* punkControl,
836 CPinBaseImpl* pPin )
838 TRACE("(%p,%p)\n",This,punkControl);
840 if ( punkControl == NULL )
842 ERR( "punkControl must not be NULL\n" );
843 return E_INVALIDARG;
846 ICOM_VTBL(This) = &imeminputpin;
847 This->punkControl = punkControl;
848 This->pPin = pPin;
849 This->pAllocator = NULL;
850 This->bReadonly = FALSE;
852 return NOERROR;
855 void CMemInputPinBaseImpl_UninitIMemInputPin(
856 CMemInputPinBaseImpl* This )
858 TRACE("(%p)\n",This);
860 if ( This->pAllocator != NULL )
862 IMemAllocator_Release(This->pAllocator);
863 This->pAllocator = NULL;
867 /***************************************************************************
869 * CQualityControlPassThruImpl
873 static HRESULT WINAPI
874 CQualityControlPassThruImpl_fnQueryInterface(IQualityControl* iface,REFIID riid,void** ppobj)
876 ICOM_THIS(CQualityControlPassThruImpl,iface);
878 TRACE("(%p)->()\n",This);
880 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
883 static ULONG WINAPI
884 CQualityControlPassThruImpl_fnAddRef(IQualityControl* iface)
886 ICOM_THIS(CQualityControlPassThruImpl,iface);
888 TRACE("(%p)->()\n",This);
890 return IUnknown_AddRef(This->punkControl);
893 static ULONG WINAPI
894 CQualityControlPassThruImpl_fnRelease(IQualityControl* iface)
896 ICOM_THIS(CQualityControlPassThruImpl,iface);
898 TRACE("(%p)->()\n",This);
900 return IUnknown_Release(This->punkControl);
904 static HRESULT WINAPI
905 CQualityControlPassThruImpl_fnNotify(IQualityControl* iface,IBaseFilter* pFilter,Quality q)
907 ICOM_THIS(CQualityControlPassThruImpl,iface);
908 HRESULT hr = S_FALSE;
910 TRACE("(%p)->()\n",This);
912 if ( This->pControl != NULL )
913 return IQualityControl_Notify( This->pControl, pFilter, q );
915 EnterCriticalSection( This->pPin->pcsPin );
916 if ( This->pPin->pHandlers->pQualityNotify != NULL )
917 hr = This->pPin->pHandlers->pQualityNotify(This->pPin,pFilter,q);
918 LeaveCriticalSection( This->pPin->pcsPin );
920 return hr;
923 static HRESULT WINAPI
924 CQualityControlPassThruImpl_fnSetSink(IQualityControl* iface,IQualityControl* pControl)
926 ICOM_THIS(CQualityControlPassThruImpl,iface);
928 TRACE("(%p)->()\n",This);
930 This->pControl = pControl; /* AddRef() must not be called */
932 return NOERROR;
935 static ICOM_VTABLE(IQualityControl) iqualitycontrol =
937 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
938 /* IUnknown fields */
939 CQualityControlPassThruImpl_fnQueryInterface,
940 CQualityControlPassThruImpl_fnAddRef,
941 CQualityControlPassThruImpl_fnRelease,
942 /* IQualityControl fields */
943 CQualityControlPassThruImpl_fnNotify,
944 CQualityControlPassThruImpl_fnSetSink,
947 HRESULT CQualityControlPassThruImpl_InitIQualityControl(
948 CQualityControlPassThruImpl* This, IUnknown* punkControl,
949 CPinBaseImpl* pPin )
951 TRACE("(%p,%p)\n",This,punkControl);
953 if ( punkControl == NULL )
955 ERR( "punkControl must not be NULL\n" );
956 return E_INVALIDARG;
959 ICOM_VTBL(This) = &iqualitycontrol;
960 This->punkControl = punkControl;
961 This->pPin = pPin;
963 return NOERROR;
966 void CQualityControlPassThruImpl_UninitIQualityControl(
967 CQualityControlPassThruImpl* This )
971 /***************************************************************************
973 * helper methods for output pins.
977 HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample )
979 if ( This->pHandlers->pReceive == NULL )
980 return E_NOTIMPL;
982 return This->pHandlers->pReceive( This, pSample );
985 HRESULT CPinBaseImpl_SendReceiveCanBlock( CPinBaseImpl* This )
987 if ( This->pHandlers->pReceiveCanBlock == NULL )
988 return E_NOTIMPL;
990 return This->pHandlers->pReceiveCanBlock( This );
993 HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This )
995 if ( This->pHandlers->pEndOfStream == NULL )
996 return E_NOTIMPL;
998 return This->pHandlers->pEndOfStream( This );
1001 HRESULT CPinBaseImpl_SendBeginFlush( CPinBaseImpl* This )
1003 if ( This->pHandlers->pBeginFlush == NULL )
1004 return E_NOTIMPL;
1006 return This->pHandlers->pBeginFlush( This );
1009 HRESULT CPinBaseImpl_SendEndFlush( CPinBaseImpl* This )
1011 if ( This->pHandlers->pEndFlush == NULL )
1012 return E_NOTIMPL;
1014 return This->pHandlers->pEndFlush( This );
1017 HRESULT CPinBaseImpl_SendNewSegment( CPinBaseImpl* This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1019 if ( This->pHandlers->pNewSegment == NULL )
1020 return E_NOTIMPL;
1022 return This->pHandlers->pNewSegment( This, rtStart, rtStop, rate );
1027 /***************************************************************************
1029 * handlers for output pins.
1033 HRESULT OutputPinSync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1035 if ( pImpl->pMemInputPinConnectedTo == NULL )
1036 return NOERROR;
1038 return IMemInputPin_Receive(pImpl->pMemInputPinConnectedTo,pSample);
1041 HRESULT OutputPinSync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1043 if ( pImpl->pMemInputPinConnectedTo == NULL )
1044 return S_FALSE;
1046 return IMemInputPin_ReceiveCanBlock(pImpl->pMemInputPinConnectedTo);
1049 HRESULT OutputPinSync_EndOfStream( CPinBaseImpl* pImpl )
1051 if ( pImpl->pPinConnectedTo == NULL )
1052 return NOERROR;
1054 return IPin_EndOfStream(pImpl->pPinConnectedTo);
1057 HRESULT OutputPinSync_BeginFlush( CPinBaseImpl* pImpl )
1059 if ( pImpl->pPinConnectedTo == NULL )
1060 return NOERROR;
1062 return IPin_BeginFlush(pImpl->pPinConnectedTo);
1065 HRESULT OutputPinSync_EndFlush( CPinBaseImpl* pImpl )
1067 if ( pImpl->pPinConnectedTo == NULL )
1068 return NOERROR;
1070 return IPin_EndFlush(pImpl->pPinConnectedTo);
1073 HRESULT OutputPinSync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1075 if ( pImpl->pPinConnectedTo == NULL )
1076 return NOERROR;
1078 return IPin_NewSegment(pImpl->pPinConnectedTo,rtStart,rtStop,rate);
1081 /***************************************************************************
1083 * handlers for output pins (async).
1087 typedef struct OutputPinTask OutputPinTask;
1089 enum OutputPinTaskType
1091 OutTask_ExitThread,
1092 OutTask_Receive,
1093 OutTask_EndOfStream,
1094 OutTask_BeginFlush,
1095 OutTask_EndFlush,
1096 OutTask_NewSegment,
1099 struct OutputPinTask
1101 OutputPinTask* pNext;
1102 enum OutputPinTaskType tasktype;
1103 IMediaSample* pSample;
1104 REFERENCE_TIME rtStart;
1105 REFERENCE_TIME rtStop;
1106 double rate;
1109 struct OutputPinAsyncImpl
1111 HANDLE m_hTaskThread;
1112 HANDLE m_hTaskEvent;
1113 IPin* m_pPin; /* connected pin */
1114 IMemInputPin* m_pMemInputPin; /* connected pin */
1115 CRITICAL_SECTION m_csTasks;
1116 OutputPinTask* m_pFirst;
1117 OutputPinTask* m_pLast;
1118 OutputPinTask* m_pTaskExitThread;
1121 static OutputPinTask* OutputPinAsync_AllocTask( enum OutputPinTaskType tasktype )
1123 OutputPinTask* pTask;
1125 pTask = (OutputPinTask*)QUARTZ_AllocMem( sizeof(OutputPinTask) );
1126 pTask->pNext = NULL;
1127 pTask->tasktype = tasktype;
1128 pTask->pSample = NULL;
1130 return pTask;
1133 static void OutputPinAsync_FreeTask( OutputPinTask* pTask )
1135 if ( pTask->pSample != NULL )
1136 IMediaSample_Release( pTask->pSample );
1137 QUARTZ_FreeMem( pTask );
1140 static void OutputPinAsync_AddTask( OutputPinAsyncImpl* This, OutputPinTask* pTask, BOOL bFirst )
1142 EnterCriticalSection( &This->m_csTasks );
1144 if ( bFirst )
1146 pTask->pNext = This->m_pFirst;
1147 This->m_pFirst = pTask;
1148 if ( This->m_pLast == NULL )
1149 This->m_pLast = pTask;
1151 else
1153 if ( This->m_pLast != NULL )
1154 This->m_pLast->pNext = pTask;
1155 else
1156 This->m_pFirst = pTask;
1157 This->m_pLast = pTask;
1160 LeaveCriticalSection( &This->m_csTasks );
1162 SetEvent( This->m_hTaskEvent );
1165 static OutputPinTask* OutputPinAsync_GetNextTask( OutputPinAsyncImpl* This )
1167 OutputPinTask* pTask;
1169 EnterCriticalSection( &This->m_csTasks );
1170 pTask = This->m_pFirst;
1171 if ( pTask != NULL )
1173 This->m_pFirst = pTask->pNext;
1174 if ( This->m_pFirst == NULL )
1175 This->m_pLast = NULL;
1176 else
1177 SetEvent( This->m_hTaskEvent );
1180 LeaveCriticalSection( &This->m_csTasks );
1182 return pTask;
1185 static DWORD WINAPI OutputPinAsync_ThreadEntry( LPVOID pv )
1187 OutputPinAsyncImpl* This = ((CPinBaseImpl*)pv)->pAsyncOut;
1188 OutputPinTask* pTask;
1189 BOOL bLoop = TRUE;
1190 BOOL bInFlush = FALSE;
1191 HRESULT hr;
1193 while ( bLoop )
1195 WaitForSingleObject( This->m_hTaskEvent, INFINITE );
1196 ResetEvent( This->m_hTaskEvent );
1198 pTask = OutputPinAsync_GetNextTask( This );
1199 if ( pTask == NULL )
1200 continue;
1202 hr = S_OK;
1203 switch ( pTask->tasktype )
1205 case OutTask_ExitThread:
1206 bLoop = FALSE;
1207 break;
1208 case OutTask_Receive:
1209 if ( !bInFlush )
1210 hr = IMemInputPin_Receive( This->m_pMemInputPin, pTask->pSample );
1211 break;
1212 case OutTask_EndOfStream:
1213 hr = IPin_EndOfStream( This->m_pPin );
1214 break;
1215 case OutTask_BeginFlush:
1216 bInFlush = TRUE;
1217 hr = IPin_BeginFlush( This->m_pPin );
1218 break;
1219 case OutTask_EndFlush:
1220 bInFlush = FALSE;
1221 hr = IPin_EndFlush( This->m_pPin );
1222 break;
1223 case OutTask_NewSegment:
1224 hr = IPin_NewSegment( This->m_pPin, pTask->rtStart, pTask->rtStop, pTask->rate );
1225 break;
1226 default:
1227 ERR( "unexpected task type %d.\n", pTask->tasktype );
1228 bLoop = FALSE;
1229 break;
1232 OutputPinAsync_FreeTask( pTask );
1234 if ( FAILED(hr) )
1236 ERR( "hresult %08lx\n", hr );
1237 bLoop = FALSE;
1241 return 0;
1244 HRESULT OutputPinAsync_OnActive( CPinBaseImpl* pImpl )
1246 HRESULT hr;
1247 DWORD dwThreadId;
1249 FIXME("(%p)\n",pImpl);
1251 if ( pImpl->pMemInputPinConnectedTo == NULL )
1252 return NOERROR;
1254 pImpl->pAsyncOut = (OutputPinAsyncImpl*)
1255 QUARTZ_AllocMem( sizeof( OutputPinAsyncImpl ) );
1256 if ( pImpl->pAsyncOut == NULL )
1257 return E_OUTOFMEMORY;
1259 InitializeCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1260 pImpl->pAsyncOut->m_hTaskThread = (HANDLE)NULL;
1261 pImpl->pAsyncOut->m_hTaskEvent = (HANDLE)NULL;
1262 pImpl->pAsyncOut->m_pFirst = NULL;
1263 pImpl->pAsyncOut->m_pLast = NULL;
1264 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1265 pImpl->pAsyncOut->m_pPin = pImpl->pPinConnectedTo;
1266 pImpl->pAsyncOut->m_pMemInputPin = pImpl->pMemInputPinConnectedTo;
1268 pImpl->pAsyncOut->m_hTaskEvent =
1269 CreateEventA( NULL, TRUE, FALSE, NULL );
1270 if ( pImpl->pAsyncOut->m_hTaskEvent == (HANDLE)NULL )
1272 hr = E_FAIL;
1273 goto err;
1276 pImpl->pAsyncOut->m_pTaskExitThread =
1277 OutputPinAsync_AllocTask( OutTask_ExitThread );
1278 if ( pImpl->pAsyncOut->m_pTaskExitThread == NULL )
1280 hr = E_OUTOFMEMORY;
1281 goto err;
1284 pImpl->pAsyncOut->m_hTaskThread = CreateThread(
1285 NULL, 0, OutputPinAsync_ThreadEntry, pImpl,
1286 0, &dwThreadId );
1287 if ( pImpl->pAsyncOut->m_hTaskThread == (HANDLE)NULL )
1289 hr = E_FAIL;
1290 goto err;
1293 return NOERROR;
1294 err:
1295 OutputPinAsync_OnInactive( pImpl );
1296 return hr;
1299 HRESULT OutputPinAsync_OnInactive( CPinBaseImpl* pImpl )
1301 OutputPinTask* pTask;
1303 FIXME("(%p)\n",pImpl);
1305 if ( pImpl->pAsyncOut == NULL )
1306 return NOERROR;
1308 if ( pImpl->pAsyncOut->m_pTaskExitThread != NULL )
1310 OutputPinAsync_AddTask( pImpl->pAsyncOut, pImpl->pAsyncOut->m_pTaskExitThread, TRUE );
1311 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1314 if ( pImpl->pAsyncOut->m_hTaskThread != (HANDLE)NULL )
1316 WaitForSingleObject( pImpl->pAsyncOut->m_hTaskThread, INFINITE );
1317 CloseHandle( pImpl->pAsyncOut->m_hTaskThread );
1319 if ( pImpl->pAsyncOut->m_hTaskEvent != (HANDLE)NULL )
1320 CloseHandle( pImpl->pAsyncOut->m_hTaskEvent );
1322 /* release all tasks. */
1323 while ( 1 )
1325 pTask = OutputPinAsync_GetNextTask( pImpl->pAsyncOut );
1326 if ( pTask == NULL )
1327 break;
1328 OutputPinAsync_FreeTask( pTask );
1331 DeleteCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1333 QUARTZ_FreeMem( pImpl->pAsyncOut );
1334 pImpl->pAsyncOut = NULL;
1336 return NOERROR;
1339 HRESULT OutputPinAsync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1341 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1342 OutputPinTask* pTask;
1344 TRACE("(%p,%p)\n",pImpl,pSample);
1346 if ( This == NULL )
1347 return NOERROR;
1349 pTask = OutputPinAsync_AllocTask( OutTask_Receive );
1350 if ( pTask == NULL )
1351 return E_OUTOFMEMORY;
1352 pTask->pSample = pSample; IMediaSample_AddRef( pSample );
1353 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1355 return NOERROR;
1358 HRESULT OutputPinAsync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1360 return S_FALSE;
1363 HRESULT OutputPinAsync_EndOfStream( CPinBaseImpl* pImpl )
1365 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1366 OutputPinTask* pTask;
1368 TRACE("(%p)\n",pImpl);
1370 if ( This == NULL )
1371 return NOERROR;
1373 pTask = OutputPinAsync_AllocTask( OutTask_EndOfStream );
1374 if ( pTask == NULL )
1375 return E_OUTOFMEMORY;
1376 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1378 return NOERROR;
1381 HRESULT OutputPinAsync_BeginFlush( CPinBaseImpl* pImpl )
1383 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1384 OutputPinTask* pTask;
1386 TRACE("(%p)\n",pImpl);
1388 if ( This == NULL )
1389 return NOERROR;
1391 pTask = OutputPinAsync_AllocTask( OutTask_BeginFlush );
1392 if ( pTask == NULL )
1393 return E_OUTOFMEMORY;
1394 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, TRUE );
1396 return NOERROR;
1399 HRESULT OutputPinAsync_EndFlush( CPinBaseImpl* pImpl )
1401 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1402 OutputPinTask* pTask;
1404 TRACE("(%p)\n",pImpl);
1406 if ( This == NULL )
1407 return NOERROR;
1409 pTask = OutputPinAsync_AllocTask( OutTask_EndFlush );
1410 if ( pTask == NULL )
1411 return E_OUTOFMEMORY;
1412 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1414 return NOERROR;
1417 HRESULT OutputPinAsync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1419 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1420 OutputPinTask* pTask;
1422 TRACE("(%p)\n",pImpl);
1424 if ( This == NULL )
1425 return NOERROR;
1427 pTask = OutputPinAsync_AllocTask( OutTask_NewSegment );
1428 if ( pTask == NULL )
1429 return E_OUTOFMEMORY;
1430 pTask->rtStart = rtStart;
1431 pTask->rtStop = rtStop;
1432 pTask->rate = rate;
1433 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1435 return NOERROR;