2 * Implements Asynchronous File/URL Source.
4 * FIXME - URL source is not implemented yet.
6 * hidenori@a2.ctktv.ne.jp
20 #include "debugtools.h"
21 DEFAULT_DEBUG_CHANNEL(quartz);
23 #include "quartz_private.h"
29 const WCHAR QUARTZ_wszAsyncFileSourceName[] =
30 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0};
31 const WCHAR QUARTZ_wszAsyncFileSourcePinName[] =
33 const WCHAR QUARTZ_wszAsyncURLSourceName[] =
34 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','U','R','L',')',0};
35 const WCHAR QUARTZ_wszAsyncURLSourcePinName[] =
40 /***************************************************************************
42 * CAsyncReaderImpl internal methods
47 AsyncSourceRequest* CAsyncReaderImpl_AllocRequest( CAsyncReaderImpl* This )
49 AsyncSourceRequest* pReq;
51 EnterCriticalSection( &This->m_csFree );
52 pReq = This->m_pFreeFirst;
54 This->m_pFreeFirst = pReq->pNext;
55 LeaveCriticalSection( &This->m_csFree );
59 pReq = (AsyncSourceRequest*)QUARTZ_AllocMem(
60 sizeof(AsyncSourceRequest) );
77 void CAsyncReaderImpl_FreeRequest( CAsyncReaderImpl* This, AsyncSourceRequest* pReq, BOOL bReleaseMem )
81 EnterCriticalSection( &This->m_csFree );
82 pReq->pNext = This->m_pFreeFirst;
83 This->m_pFreeFirst = pReq;
84 LeaveCriticalSection( &This->m_csFree );
88 QUARTZ_FreeMem( pReq );
93 AsyncSourceRequest* CAsyncReaderImpl_GetRequest( CAsyncReaderImpl* This )
95 AsyncSourceRequest* pReq;
97 EnterCriticalSection( &This->m_csRequest );
98 pReq = This->m_pRequestFirst;
100 This->m_pRequestFirst = pReq->pNext;
101 LeaveCriticalSection( &This->m_csRequest );
107 AsyncSourceRequest* CAsyncReaderImpl_GetReply( CAsyncReaderImpl* This )
109 AsyncSourceRequest* pReq;
111 EnterCriticalSection( &This->m_csReply );
112 pReq = This->m_pReplyFirst;
114 This->m_pReplyFirst = pReq->pNext;
115 LeaveCriticalSection( &This->m_csReply );
121 void CAsyncReaderImpl_PostRequest( CAsyncReaderImpl* This, AsyncSourceRequest* pReq )
123 /* FIXME - add to tail */
124 EnterCriticalSection( &This->m_csRequest );
125 pReq->pNext = This->m_pRequestFirst;
126 This->m_pRequestFirst = pReq;
127 if ( This->m_hEventReqQueued != (HANDLE)NULL )
128 SetEvent( This->m_hEventReqQueued );
129 LeaveCriticalSection( &This->m_csRequest );
133 void CAsyncReaderImpl_PostReply( CAsyncReaderImpl* This, AsyncSourceRequest* pReq )
135 /* FIXME - add to tail */
136 EnterCriticalSection( &This->m_csReply );
137 pReq->pNext = This->m_pReplyFirst;
138 This->m_pReplyFirst = pReq;
139 if ( This->m_hEventSampQueued != (HANDLE)NULL )
140 SetEvent( This->m_hEventSampQueued );
141 LeaveCriticalSection( &This->m_csReply );
145 void CAsyncReaderImpl_ReleaseReqList( CAsyncReaderImpl* This, AsyncSourceRequest** ppReq, BOOL bReleaseMem )
147 AsyncSourceRequest* pReq;
148 AsyncSourceRequest* pReqNext;
150 TRACE("(%p,%p,%d)\n",This,*ppReq,bReleaseMem);
151 pReq = *ppReq; *ppReq = NULL;
152 while ( pReq != NULL )
154 pReqNext = pReq->pNext;
155 CAsyncReaderImpl_FreeRequest(This,pReq,bReleaseMem);
161 CAsyncReaderImpl_ThreadEntry( LPVOID pv )
163 CAsyncReaderImpl* This = (CAsyncReaderImpl*)pv;
164 HANDLE hWaitEvents[2];
167 AsyncSourceRequest* pReq = NULL;
169 SetEvent( This->m_hEventInit );
171 hWaitEvents[0] = This->m_hEventReqQueued;
172 hWaitEvents[1] = This->m_hEventCancel;
174 TRACE("enter message loop.\n");
178 ResetEvent( This->m_hEventReqQueued );
179 pReq = CAsyncReaderImpl_GetRequest(This);
182 dwRes = WaitForMultipleObjects(2,hWaitEvents,FALSE,INFINITE);
183 if ( dwRes != WAIT_OBJECT_0 )
185 if ( This->m_bAbortThread )
191 /* process a queued request */
192 EnterCriticalSection( &This->m_csReader );
193 hr = This->pSource->m_pHandler->pRead( This->pSource, pReq->llStart, pReq->lLength, pReq->pBuf, &pReq->lActual, This->m_hEventCancel );
194 LeaveCriticalSection( &This->m_csReader );
203 if ( This->m_bAbortThread )
205 ResetEvent( This->m_hEventCancel );
208 CAsyncReaderImpl_PostReply( This, pReq );
209 SetEvent( This->m_hEventSampQueued );
214 CAsyncReaderImpl_PostRequest( This, pReq );
216 SetEvent( This->m_hEventSampQueued );
221 CAsyncReaderImpl_BeginThread( CAsyncReaderImpl* This )
227 if ( This->m_hEventInit != (HANDLE)NULL ||
228 This->m_hEventCancel != (HANDLE)NULL ||
229 This->m_hEventReqQueued != (HANDLE)NULL ||
230 This->m_hEventSampQueued != (HANDLE)NULL ||
231 This->m_hThread != (HANDLE)NULL )
233 This->m_bAbortThread = FALSE;
235 This->m_hEventInit = CreateEventA(NULL,TRUE,FALSE,NULL);
236 if ( This->m_hEventInit == (HANDLE)NULL )
237 return E_OUTOFMEMORY;
238 This->m_hEventCancel = CreateEventA(NULL,TRUE,FALSE,NULL);
239 if ( This->m_hEventCancel == (HANDLE)NULL )
240 return E_OUTOFMEMORY;
241 This->m_hEventReqQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
242 if ( This->m_hEventReqQueued == (HANDLE)NULL )
243 return E_OUTOFMEMORY;
244 This->m_hEventSampQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
245 if ( This->m_hEventSampQueued == (HANDLE)NULL )
246 return E_OUTOFMEMORY;
248 /* create the processing thread. */
249 This->m_hThread = CreateThread(
251 CAsyncReaderImpl_ThreadEntry,
254 if ( This->m_hThread == (HANDLE)NULL )
257 hEvents[0] = This->m_hEventInit;
258 hEvents[1] = This->m_hThread;
260 dwRes = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
261 if ( dwRes != WAIT_OBJECT_0 )
268 CAsyncReaderImpl_EndThread( CAsyncReaderImpl* This )
270 if ( This->m_hThread != (HANDLE)NULL )
274 This->m_bAbortThread = TRUE;
275 SetEvent( This->m_hEventCancel );
276 if ( WaitForSingleObject( This->m_hThread, 100 ) == WAIT_OBJECT_0 )
279 CloseHandle( This->m_hThread );
280 This->m_hThread = (HANDLE)NULL;
282 if ( This->m_hEventInit != (HANDLE)NULL )
284 CloseHandle( This->m_hEventInit );
285 This->m_hEventInit = (HANDLE)NULL;
287 if ( This->m_hEventCancel != (HANDLE)NULL )
289 CloseHandle( This->m_hEventCancel );
290 This->m_hEventCancel = (HANDLE)NULL;
292 if ( This->m_hEventReqQueued != (HANDLE)NULL )
294 CloseHandle( This->m_hEventReqQueued );
295 This->m_hEventReqQueued = (HANDLE)NULL;
297 if ( This->m_hEventSampQueued != (HANDLE)NULL )
299 CloseHandle( This->m_hEventSampQueued );
300 This->m_hEventSampQueued = (HANDLE)NULL;
304 /***************************************************************************
306 * CAsyncReaderImpl methods
310 static HRESULT WINAPI
311 CAsyncReaderImpl_fnQueryInterface(IAsyncReader* iface,REFIID riid,void** ppobj)
313 ICOM_THIS(CAsyncReaderImpl,iface);
315 TRACE("(%p)->()\n",This);
317 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
321 CAsyncReaderImpl_fnAddRef(IAsyncReader* iface)
323 ICOM_THIS(CAsyncReaderImpl,iface);
325 TRACE("(%p)->()\n",This);
327 return IUnknown_AddRef(This->punkControl);
331 CAsyncReaderImpl_fnRelease(IAsyncReader* iface)
333 ICOM_THIS(CAsyncReaderImpl,iface);
335 TRACE("(%p)->()\n",This);
337 return IUnknown_Release(This->punkControl);
340 static HRESULT WINAPI
341 CAsyncReaderImpl_fnRequestAllocator(IAsyncReader* iface,IMemAllocator* pAlloc,ALLOCATOR_PROPERTIES* pProp,IMemAllocator** ppAllocActual)
343 ICOM_THIS(CAsyncReaderImpl,iface);
345 ALLOCATOR_PROPERTIES propActual;
346 IUnknown* punk = NULL;
348 TRACE("(%p)->(%p,%p,%p)\n",This,pAlloc,pProp,ppAllocActual);
350 if ( pAlloc == NULL || pProp == NULL || ppAllocActual == NULL )
353 IMemAllocator_AddRef(pAlloc);
354 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
357 *ppAllocActual = pAlloc;
360 IMemAllocator_Release(pAlloc);
362 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
365 hr = IUnknown_QueryInterface( punk, &IID_IMemAllocator, (void**)&pAlloc );
366 IUnknown_Release(punk);
370 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
373 *ppAllocActual = pAlloc;
376 IMemAllocator_Release(pAlloc);
381 static HRESULT WINAPI
382 CAsyncReaderImpl_fnRequest(IAsyncReader* iface,IMediaSample* pSample,DWORD_PTR dwContext)
384 ICOM_THIS(CAsyncReaderImpl,iface);
385 HRESULT hr = NOERROR;
386 REFERENCE_TIME rtStart;
387 REFERENCE_TIME rtEnd;
388 AsyncSourceRequest* pReq;
391 TRACE("(%p)->(%p,%u)\n",This,pSample,dwContext);
393 hr = IMediaSample_GetPointer(pSample,&pData);
395 hr = IMediaSample_GetTime(pSample,&rtStart,&rtEnd);
399 pReq = CAsyncReaderImpl_AllocRequest(This);
401 return E_OUTOFMEMORY;
403 pReq->llStart = rtStart / QUARTZ_TIMEUNITS;
404 pReq->lLength = (LONG)(rtEnd / QUARTZ_TIMEUNITS - rtStart / QUARTZ_TIMEUNITS);
407 pReq->pSample = pSample;
408 pReq->dwContext = dwContext;
409 CAsyncReaderImpl_PostRequest( This, pReq );
414 static HRESULT WINAPI
415 CAsyncReaderImpl_fnWaitForNext(IAsyncReader* iface,DWORD dwTimeout,IMediaSample** ppSample,DWORD_PTR* pdwContext)
417 ICOM_THIS(CAsyncReaderImpl,iface);
418 HRESULT hr = NOERROR;
420 AsyncSourceRequest* pReq;
421 REFERENCE_TIME rtStart;
422 REFERENCE_TIME rtEnd;
424 TRACE("(%p)->(%lu,%p,%p)\n",This,dwTimeout,ppSample,pdwContext);
426 EnterCriticalSection( &This->m_csRequest );
427 if ( This->m_bInFlushing )
429 LeaveCriticalSection( &This->m_csRequest );
433 ResetEvent( This->m_hEventSampQueued );
434 pReq = CAsyncReaderImpl_GetReply(This);
437 dwRes = WaitForSingleObject( This->m_hEventSampQueued, dwTimeout );
438 if ( dwRes == WAIT_OBJECT_0 )
439 pReq = CAsyncReaderImpl_GetReply(This);
443 hr = IMediaSample_SetActualDataLength(pReq->pSample,pReq->lActual);
446 rtStart = pReq->llStart * QUARTZ_TIMEUNITS;
447 rtEnd = (pReq->llStart + pReq->lActual) * QUARTZ_TIMEUNITS;
448 hr = IMediaSample_SetTime(pReq->pSample,&rtStart,&rtEnd);
450 *ppSample = pReq->pSample;
451 *pdwContext = pReq->dwContext;
452 if ( hr == S_OK && pReq->lActual != pReq->lLength )
464 static HRESULT WINAPI
465 CAsyncReaderImpl_fnSyncReadAligned(IAsyncReader* iface,IMediaSample* pSample)
467 ICOM_THIS(CAsyncReaderImpl,iface);
469 REFERENCE_TIME rtStart;
470 REFERENCE_TIME rtEnd;
476 TRACE("(%p)->(%p)\n",This,pSample);
478 hr = IMediaSample_GetPointer(pSample,&pData);
480 hr = IMediaSample_GetTime(pSample,&rtStart,&rtEnd);
484 llStart = rtStart / QUARTZ_TIMEUNITS;
485 lLength = (LONG)(rtEnd / QUARTZ_TIMEUNITS - rtStart / QUARTZ_TIMEUNITS);
488 EnterCriticalSection( &This->m_csReader );
489 hr = This->pSource->m_pHandler->pRead( This->pSource, llStart, lLength, pData, &lActual, (HANDLE)NULL );
490 LeaveCriticalSection( &This->m_csReader );
494 hr = IMediaSample_SetActualDataLength(pSample,lActual);
497 rtStart = llStart * QUARTZ_TIMEUNITS;
498 rtEnd = (llStart + lActual) * QUARTZ_TIMEUNITS;
499 hr = IMediaSample_SetTime(pSample,&rtStart,&rtEnd);
501 if ( hr == S_OK && lActual != lLength )
508 static HRESULT WINAPI
509 CAsyncReaderImpl_fnSyncRead(IAsyncReader* iface,LONGLONG llPosStart,LONG lLength,BYTE* pbBuf)
511 ICOM_THIS(CAsyncReaderImpl,iface);
515 TRACE("(%p)->()\n",This);
517 EnterCriticalSection( &This->m_csReader );
518 hr = This->pSource->m_pHandler->pRead( This->pSource, llPosStart, lLength, pbBuf, &lActual, (HANDLE)NULL );
519 LeaveCriticalSection( &This->m_csReader );
521 if ( hr == S_OK && lLength != lActual )
527 static HRESULT WINAPI
528 CAsyncReaderImpl_fnLength(IAsyncReader* iface,LONGLONG* pllTotal,LONGLONG* pllAvailable)
530 ICOM_THIS(CAsyncReaderImpl,iface);
533 TRACE("(%p)->()\n",This);
535 hr = This->pSource->m_pHandler->pGetLength( This->pSource, pllTotal, pllAvailable );
540 static HRESULT WINAPI
541 CAsyncReaderImpl_fnBeginFlush(IAsyncReader* iface)
543 ICOM_THIS(CAsyncReaderImpl,iface);
545 TRACE("(%p)->()\n",This);
547 EnterCriticalSection( &This->m_csRequest );
548 This->m_bInFlushing = TRUE;
549 SetEvent( This->m_hEventCancel );
550 CAsyncReaderImpl_ReleaseReqList(This,&This->m_pRequestFirst,FALSE);
551 LeaveCriticalSection( &This->m_csRequest );
556 static HRESULT WINAPI
557 CAsyncReaderImpl_fnEndFlush(IAsyncReader* iface)
559 ICOM_THIS(CAsyncReaderImpl,iface);
561 TRACE("(%p)->()\n",This);
563 EnterCriticalSection( &This->m_csRequest );
564 This->m_bInFlushing = FALSE;
565 ResetEvent( This->m_hEventCancel );
566 LeaveCriticalSection( &This->m_csRequest );
572 static ICOM_VTABLE(IAsyncReader) iasyncreader =
574 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
575 /* IUnknown fields */
576 CAsyncReaderImpl_fnQueryInterface,
577 CAsyncReaderImpl_fnAddRef,
578 CAsyncReaderImpl_fnRelease,
580 /* IAsyncReader fields */
581 CAsyncReaderImpl_fnRequestAllocator,
582 CAsyncReaderImpl_fnRequest,
583 CAsyncReaderImpl_fnWaitForNext,
584 CAsyncReaderImpl_fnSyncReadAligned,
585 CAsyncReaderImpl_fnSyncRead,
586 CAsyncReaderImpl_fnLength,
587 CAsyncReaderImpl_fnBeginFlush,
588 CAsyncReaderImpl_fnEndFlush,
591 HRESULT CAsyncReaderImpl_InitIAsyncReader(
592 CAsyncReaderImpl* This, IUnknown* punkControl,
593 CAsyncSourceImpl* pSource )
595 TRACE("(%p,%p)\n",This,punkControl);
597 if ( punkControl == NULL )
599 ERR( "punkControl must not be NULL\n" );
603 ICOM_VTBL(This) = &iasyncreader;
604 This->punkControl = punkControl;
605 This->pSource = pSource;
606 This->m_bInFlushing = FALSE;
607 This->m_bAbortThread = FALSE;
608 This->m_hEventInit = (HANDLE)NULL;
609 This->m_hEventCancel = (HANDLE)NULL;
610 This->m_hEventReqQueued = (HANDLE)NULL;
611 This->m_hEventSampQueued = (HANDLE)NULL;
612 This->m_hThread = (HANDLE)NULL;
613 This->m_pRequestFirst = NULL;
614 This->m_pReplyFirst = NULL;
615 This->m_pFreeFirst = NULL;
617 InitializeCriticalSection( &This->m_csReader );
618 InitializeCriticalSection( &This->m_csRequest );
619 InitializeCriticalSection( &This->m_csReply );
620 InitializeCriticalSection( &This->m_csFree );
625 void CAsyncReaderImpl_UninitIAsyncReader(
626 CAsyncReaderImpl* This )
628 TRACE("(%p) enter\n",This);
630 CAsyncReaderImpl_ReleaseReqList(This,&This->m_pRequestFirst,TRUE);
631 CAsyncReaderImpl_ReleaseReqList(This,&This->m_pReplyFirst,TRUE);
632 CAsyncReaderImpl_ReleaseReqList(This,&This->m_pFreeFirst,TRUE);
634 DeleteCriticalSection( &This->m_csReader );
635 DeleteCriticalSection( &This->m_csRequest );
636 DeleteCriticalSection( &This->m_csReply );
637 DeleteCriticalSection( &This->m_csFree );
639 TRACE("(%p) leave\n",This);
642 /***************************************************************************
644 * CFileSourceFilterImpl
648 static HRESULT WINAPI
649 CFileSourceFilterImpl_fnQueryInterface(IFileSourceFilter* iface,REFIID riid,void** ppobj)
651 ICOM_THIS(CFileSourceFilterImpl,iface);
653 TRACE("(%p)->()\n",This);
655 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
659 CFileSourceFilterImpl_fnAddRef(IFileSourceFilter* iface)
661 ICOM_THIS(CFileSourceFilterImpl,iface);
663 TRACE("(%p)->()\n",This);
665 return IUnknown_AddRef(This->punkControl);
669 CFileSourceFilterImpl_fnRelease(IFileSourceFilter* iface)
671 ICOM_THIS(CFileSourceFilterImpl,iface);
673 TRACE("(%p)->()\n",This);
675 return IUnknown_Release(This->punkControl);
678 static HRESULT WINAPI
679 CFileSourceFilterImpl_fnLoad(IFileSourceFilter* iface,LPCOLESTR pFileName,const AM_MEDIA_TYPE* pmt)
681 ICOM_THIS(CFileSourceFilterImpl,iface);
684 TRACE("(%p)->(%s,%p)\n",This,debugstr_w(pFileName),pmt);
686 if ( pFileName == NULL )
689 if ( This->m_pwszFileName != NULL )
692 This->m_cbFileName = sizeof(WCHAR)*(lstrlenW(pFileName)+1);
693 This->m_pwszFileName = (WCHAR*)QUARTZ_AllocMem( This->m_cbFileName );
694 if ( This->m_pwszFileName == NULL )
695 return E_OUTOFMEMORY;
696 memcpy( This->m_pwszFileName, pFileName, This->m_cbFileName );
700 hr = QUARTZ_MediaType_Copy( &This->m_mt, pmt );
706 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
707 memcpy( &This->m_mt.majortype, &MEDIATYPE_Stream, sizeof(GUID) );
708 memcpy( &This->m_mt.subtype, &MEDIASUBTYPE_NULL, sizeof(GUID) );
709 This->m_mt.lSampleSize = 1;
710 memcpy( &This->m_mt.formattype, &FORMAT_None, sizeof(GUID) );
713 hr = This->pSource->m_pHandler->pLoad( This->pSource, pFileName );
717 This->pSource->pPin->pin.pmtAcceptTypes = &This->m_mt;
718 This->pSource->pPin->pin.cAcceptTypes = 1;
725 static HRESULT WINAPI
726 CFileSourceFilterImpl_fnGetCurFile(IFileSourceFilter* iface,LPOLESTR* ppFileName,AM_MEDIA_TYPE* pmt)
728 ICOM_THIS(CFileSourceFilterImpl,iface);
729 HRESULT hr = E_NOTIMPL;
731 TRACE("(%p)->(%p,%p)\n",This,ppFileName,pmt);
733 if ( ppFileName == NULL || pmt == NULL )
736 if ( This->m_pwszFileName == NULL )
739 hr = QUARTZ_MediaType_Copy( pmt, &This->m_mt );
743 *ppFileName = (WCHAR*)CoTaskMemAlloc( This->m_cbFileName );
744 if ( *ppFileName == NULL )
746 QUARTZ_MediaType_Free(pmt);
747 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
748 return E_OUTOFMEMORY;
751 memcpy( *ppFileName, This->m_pwszFileName, This->m_cbFileName );
756 static ICOM_VTABLE(IFileSourceFilter) ifilesource =
758 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
759 /* IUnknown fields */
760 CFileSourceFilterImpl_fnQueryInterface,
761 CFileSourceFilterImpl_fnAddRef,
762 CFileSourceFilterImpl_fnRelease,
763 /* IFileSourceFilter fields */
764 CFileSourceFilterImpl_fnLoad,
765 CFileSourceFilterImpl_fnGetCurFile,
768 HRESULT CFileSourceFilterImpl_InitIFileSourceFilter(
769 CFileSourceFilterImpl* This, IUnknown* punkControl,
770 CAsyncSourceImpl* pSource,
771 CRITICAL_SECTION* pcsFileSource )
773 TRACE("(%p,%p)\n",This,punkControl);
775 if ( punkControl == NULL )
777 ERR( "punkControl must not be NULL\n" );
781 ICOM_VTBL(This) = &ifilesource;
782 This->punkControl = punkControl;
783 This->pSource = pSource;
784 This->pcsFileSource = pcsFileSource;
785 This->m_pwszFileName = NULL;
786 This->m_cbFileName = 0;
787 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
792 void CFileSourceFilterImpl_UninitIFileSourceFilter(
793 CFileSourceFilterImpl* This )
795 TRACE("(%p)\n",This);
797 This->pSource->m_pHandler->pCleanup( This->pSource );
798 if ( This->m_pwszFileName != NULL )
799 QUARTZ_FreeMem( This->m_pwszFileName );
800 QUARTZ_MediaType_Free( &This->m_mt );
803 /***************************************************************************
805 * CAsyncSourcePinImpl methods
810 static HRESULT CAsyncSourcePinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
812 CAsyncSourcePinImpl_THIS(pImpl,pin);
814 TRACE("(%p,%p)\n",This,pPin);
816 This->bAsyncReaderQueried = FALSE;
821 static HRESULT CAsyncSourcePinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
823 CAsyncSourcePinImpl_THIS(pImpl,pin);
825 TRACE("(%p,%p)\n",This,pPin);
827 if ( !This->bAsyncReaderQueried )
833 static HRESULT CAsyncSourcePinImpl_OnDisconnect( CPinBaseImpl* pImpl )
835 CAsyncSourcePinImpl_THIS(pImpl,pin);
837 TRACE("(%p)\n",This);
839 This->bAsyncReaderQueried = FALSE;
844 static HRESULT CAsyncSourcePinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
846 CAsyncSourcePinImpl_THIS(pImpl,pin);
848 TRACE("(%p,%p)\n",This,pmt);
852 if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
858 static const CBasePinHandlers outputpinhandlers =
860 CAsyncSourcePinImpl_OnPreConnect, /* pOnPreConnect */
861 CAsyncSourcePinImpl_OnPostConnect, /* pOnPostConnect */
862 CAsyncSourcePinImpl_OnDisconnect, /* pOnDisconnect */
863 CAsyncSourcePinImpl_CheckMediaType, /* pCheckMediaType */
864 NULL, /* pQualityNotify */
866 NULL, /* pReceiveCanBlock */
867 NULL, /* pEndOfStream */
868 NULL, /* pBeginFlush */
869 NULL, /* pEndFlush */
870 NULL, /* pNewSegment */
873 /***************************************************************************
875 * CAsyncSourceImpl methods
879 static HRESULT CAsyncSourceImpl_OnActive( CBaseFilterImpl* pImpl )
881 CAsyncSourceImpl_THIS(pImpl,basefilter);
884 TRACE( "(%p)\n", This );
886 hr = CAsyncReaderImpl_BeginThread(&This->pPin->async);
893 static HRESULT CAsyncSourceImpl_OnInactive( CBaseFilterImpl* pImpl )
895 CAsyncSourceImpl_THIS(pImpl,basefilter);
897 TRACE( "(%p)\n", This );
899 CAsyncReaderImpl_EndThread(&This->pPin->async);
904 static const CBaseFilterHandlers filterhandlers =
906 CAsyncSourceImpl_OnActive, /* pOnActive */
907 CAsyncSourceImpl_OnInactive, /* pOnInactive */
911 /***************************************************************************
913 * new/delete CAsyncSourceImpl
917 /* can I use offsetof safely? - FIXME? */
918 static QUARTZ_IFEntry FilterIFEntries[] =
920 { &IID_IPersist, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
921 { &IID_IMediaFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
922 { &IID_IBaseFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
923 { &IID_IFileSourceFilter, offsetof(CAsyncSourceImpl,filesrc)-offsetof(CAsyncSourceImpl,unk) },
926 static void QUARTZ_DestroyAsyncSource(IUnknown* punk)
928 CAsyncSourceImpl_THIS(punk,unk);
930 TRACE( "(%p)\n", This );
932 if ( This->pPin != NULL )
934 IUnknown_Release(This->pPin->unk.punkControl);
938 This->m_pHandler->pCleanup( This );
940 CFileSourceFilterImpl_UninitIFileSourceFilter(&This->filesrc);
941 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
943 DeleteCriticalSection( &This->csFilter );
946 HRESULT QUARTZ_CreateAsyncSource(
947 IUnknown* punkOuter,void** ppobj,
948 const CLSID* pclsidAsyncSource,
949 LPCWSTR pwszAsyncSourceName,
950 LPCWSTR pwszOutPinName,
951 const AsyncSourceHandlers* pHandler )
953 CAsyncSourceImpl* This = NULL;
956 TRACE("(%p,%p)\n",punkOuter,ppobj);
958 This = (CAsyncSourceImpl*)
959 QUARTZ_AllocObj( sizeof(CAsyncSourceImpl) );
961 return E_OUTOFMEMORY;
964 This->m_pHandler = pHandler;
965 This->m_pUserData = NULL;
967 QUARTZ_IUnkInit( &This->unk, punkOuter );
969 hr = CBaseFilterImpl_InitIBaseFilter(
971 This->unk.punkControl,
977 /* construct this class. */
978 hr = CFileSourceFilterImpl_InitIFileSourceFilter(
979 &This->filesrc, This->unk.punkControl,
980 This, &This->csFilter );
983 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
989 QUARTZ_FreeObj(This);
993 This->unk.pEntries = FilterIFEntries;
994 This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]);
995 This->unk.pOnFinalRelease = QUARTZ_DestroyAsyncSource;
996 InitializeCriticalSection( &This->csFilter );
998 /* create the output pin. */
999 hr = QUARTZ_CreateAsyncSourcePin(
1000 This, &This->csFilter,
1001 &This->pPin, pwszOutPinName );
1002 if ( SUCCEEDED(hr) )
1003 hr = QUARTZ_CompList_AddComp(
1004 This->basefilter.pOutPins,
1005 (IUnknown*)&(This->pPin->pin),
1010 IUnknown_Release( This->unk.punkControl );
1014 *ppobj = (void*)&(This->unk);
1019 /***************************************************************************
1021 * new/delete CAsyncSourcePinImpl
1025 /* can I use offsetof safely? - FIXME? */
1026 static QUARTZ_IFEntry OutPinIFEntries[] =
1028 { &IID_IPin, offsetof(CAsyncSourcePinImpl,pin)-offsetof(CAsyncSourcePinImpl,unk) },
1029 /***{ &IID_IAsyncReader, offsetof(CAsyncSourcePinImpl,async)-offsetof(CAsyncSourcePinImpl,unk) },***/
1032 static HRESULT CAsyncSourceImpl_OnQueryInterface(
1033 IUnknown* punk, const IID* piid, void** ppobj )
1035 CAsyncSourcePinImpl_THIS(punk,unk);
1037 if ( IsEqualGUID( &IID_IAsyncReader, piid ) )
1039 TRACE("IAsyncReader has been queried.\n");
1040 *ppobj = (void*)&This->async;
1041 IUnknown_AddRef(punk);
1042 This->bAsyncReaderQueried = TRUE;
1046 return E_NOINTERFACE;
1049 static void QUARTZ_DestroyAsyncSourcePin(IUnknown* punk)
1051 CAsyncSourcePinImpl_THIS(punk,unk);
1053 TRACE( "(%p)\n", This );
1055 CAsyncReaderImpl_UninitIAsyncReader( &This->async );
1056 CPinBaseImpl_UninitIPin( &This->pin );
1059 HRESULT QUARTZ_CreateAsyncSourcePin(
1060 CAsyncSourceImpl* pFilter,
1061 CRITICAL_SECTION* pcsPin,
1062 CAsyncSourcePinImpl** ppPin,
1063 LPCWSTR pwszPinName )
1065 CAsyncSourcePinImpl* This = NULL;
1068 TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
1070 This = (CAsyncSourcePinImpl*)
1071 QUARTZ_AllocObj( sizeof(CAsyncSourcePinImpl) );
1073 return E_OUTOFMEMORY;
1075 QUARTZ_IUnkInit( &This->unk, NULL );
1076 This->qiext.pNext = NULL;
1077 This->qiext.pOnQueryInterface = &CAsyncSourceImpl_OnQueryInterface;
1078 QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
1080 This->bAsyncReaderQueried = FALSE;
1081 This->pSource = pFilter;
1083 hr = CPinBaseImpl_InitIPin(
1085 This->unk.punkControl,
1087 &pFilter->basefilter,
1090 &outputpinhandlers );
1092 if ( SUCCEEDED(hr) )
1094 hr = CAsyncReaderImpl_InitIAsyncReader(
1096 This->unk.punkControl,
1100 CPinBaseImpl_UninitIPin( &This->pin );
1106 QUARTZ_FreeObj(This);
1110 This->unk.pEntries = OutPinIFEntries;
1111 This->unk.dwEntries = sizeof(OutPinIFEntries)/sizeof(OutPinIFEntries[0]);
1112 This->unk.pOnFinalRelease = QUARTZ_DestroyAsyncSourcePin;
1116 TRACE("returned successfully.\n");
1123 /***************************************************************************
1125 * Implements File Source.
1129 typedef struct AsyncSourceFileImpl
1133 } AsyncSourceFileImpl;
1136 static HRESULT AsyncSourceFileImpl_Load( CAsyncSourceImpl* pImpl, LPCWSTR lpwszSourceName )
1138 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1143 return E_UNEXPECTED;
1144 This = (AsyncSourceFileImpl*)QUARTZ_AllocMem( sizeof(AsyncSourceFileImpl) );
1145 pImpl->m_pUserData = (void*)This;
1147 return E_OUTOFMEMORY;
1148 This->hFile = INVALID_HANDLE_VALUE;
1151 This->hFile = CreateFileW( lpwszSourceName,
1152 GENERIC_READ, FILE_SHARE_READ,
1153 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL );
1154 if ( This->hFile == INVALID_HANDLE_VALUE )
1157 SetLastError(NO_ERROR);
1158 dwLow = GetFileSize( This->hFile, &dwHigh );
1159 if ( dwLow == 0xffffffff && GetLastError() != NO_ERROR )
1162 This->llTotal = (LONGLONG)dwLow | ((LONGLONG)dwHigh << 32);
1167 static HRESULT AsyncSourceFileImpl_Cleanup( CAsyncSourceImpl* pImpl )
1169 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1174 if ( This->hFile != INVALID_HANDLE_VALUE )
1175 CloseHandle(This->hFile);
1177 QUARTZ_FreeMem(This);
1178 pImpl->m_pUserData = NULL;
1183 static HRESULT AsyncSourceFileImpl_GetLength( CAsyncSourceImpl* pImpl, LONGLONG* pllTotal, LONGLONG* pllAvailable )
1185 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1188 return E_UNEXPECTED;
1190 *pllTotal = This->llTotal;
1191 *pllAvailable = This->llTotal;
1196 static HRESULT AsyncSourceFileImpl_Read( CAsyncSourceImpl* pImpl, LONGLONG llOfsStart, LONG lLength, BYTE* pBuf, LONG* plReturned, HANDLE hEventCancel )
1198 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1206 if ( This == NULL || This->hFile == INVALID_HANDLE_VALUE )
1207 return E_UNEXPECTED;
1211 lOfsLow = (LONG)(llOfsStart & 0xffffffff);
1212 lOfsHigh = (LONG)(llOfsStart >> 32);
1213 SetLastError(NO_ERROR);
1214 lOfsLow = SetFilePointer( This->hFile, lOfsLow, &lOfsHigh, FILE_BEGIN );
1215 if ( lOfsLow == (LONG)0xffffffff && GetLastError() != NO_ERROR )
1218 while ( lLength > 0 )
1220 if ( hEventCancel != (HANDLE)NULL &&
1221 WaitForSingleObject( hEventCancel, 0 ) == WAIT_OBJECT_0 )
1227 lBlock = ( lLength > ASYNCSRC_FILE_BLOCKSIZE ) ?
1228 ASYNCSRC_FILE_BLOCKSIZE : lLength;
1230 if ( !ReadFile(This->hFile,pBuf,(DWORD)lBlock,&dw,NULL) )
1236 lReturned += (LONG)dw;
1237 lLength -= (LONG)dw;
1238 if ( lBlock > (LONG)dw )
1242 *plReturned = lReturned;
1247 static const struct AsyncSourceHandlers asyncsrc_file =
1249 AsyncSourceFileImpl_Load,
1250 AsyncSourceFileImpl_Cleanup,
1251 AsyncSourceFileImpl_GetLength,
1252 AsyncSourceFileImpl_Read,
1255 HRESULT QUARTZ_CreateAsyncReader(IUnknown* punkOuter,void** ppobj)
1257 return QUARTZ_CreateAsyncSource(
1260 QUARTZ_wszAsyncFileSourceName,
1261 QUARTZ_wszAsyncFileSourcePinName,
1265 /***************************************************************************
1267 * Implements URL Source.
1271 typedef struct AsyncSourceURLImpl
1274 } AsyncSourceURLImpl;
1277 static HRESULT AsyncSourceURLImpl_Load( CAsyncSourceImpl* pImpl, LPCWSTR lpwszSourceName )
1279 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1281 FIXME("(%p,%p) stub!\n", pImpl, lpwszSourceName);
1284 return E_UNEXPECTED;
1285 This = (AsyncSourceURLImpl*)QUARTZ_AllocMem( sizeof(AsyncSourceURLImpl) );
1286 pImpl->m_pUserData = (void*)This;
1288 return E_OUTOFMEMORY;
1293 static HRESULT AsyncSourceURLImpl_Cleanup( CAsyncSourceImpl* pImpl )
1295 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1297 FIXME("(%p) stub!\n", This);
1302 QUARTZ_FreeMem(This);
1303 pImpl->m_pUserData = NULL;
1308 static HRESULT AsyncSourceURLImpl_GetLength( CAsyncSourceImpl* pImpl, LONGLONG* pllTotal, LONGLONG* pllAvailable )
1310 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1312 FIXME("(%p,%p,%p) stub!\n", This, pllTotal, pllAvailable);
1315 return E_UNEXPECTED;
1320 static HRESULT AsyncSourceURLImpl_Read( CAsyncSourceImpl* pImpl, LONGLONG llOfsStart, LONG lLength, BYTE* pBuf, LONG* plReturned, HANDLE hEventCancel )
1322 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1324 FIXME("(%p) stub!\n", This);
1327 return E_UNEXPECTED;
1332 static const struct AsyncSourceHandlers asyncsrc_url =
1334 AsyncSourceURLImpl_Load,
1335 AsyncSourceURLImpl_Cleanup,
1336 AsyncSourceURLImpl_GetLength,
1337 AsyncSourceURLImpl_Read,
1341 HRESULT QUARTZ_CreateURLReader(IUnknown* punkOuter,void** ppobj)
1343 return QUARTZ_CreateAsyncSource(
1346 QUARTZ_wszAsyncURLSourceName,
1347 QUARTZ_wszAsyncURLSourcePinName,