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* pReq, BOOL bReleaseMem )
147 AsyncSourceRequest* pReqNext;
149 while ( pReq != NULL )
151 pReqNext = pReq->pNext;
152 CAsyncReaderImpl_FreeRequest(This,pReq,bReleaseMem);
158 CAsyncReaderImpl_ThreadEntry( LPVOID pv )
160 CAsyncReaderImpl* This = (CAsyncReaderImpl*)pv;
161 HANDLE hWaitEvents[2];
164 AsyncSourceRequest* pReq = NULL;
166 SetEvent( This->m_hEventInit );
168 hWaitEvents[0] = This->m_hEventReqQueued;
169 hWaitEvents[1] = This->m_hEventCancel;
171 TRACE("enter message loop.\n");
175 ResetEvent( This->m_hEventReqQueued );
176 pReq = CAsyncReaderImpl_GetRequest(This);
179 dwRes = WaitForMultipleObjects(2,hWaitEvents,FALSE,INFINITE);
180 if ( dwRes != WAIT_OBJECT_0 )
182 if ( This->m_bAbortThread )
188 /* process a queued request */
189 EnterCriticalSection( &This->m_csReader );
190 hr = This->pSource->m_pHandler->pRead( This->pSource, pReq->llStart, pReq->lLength, pReq->pBuf, &pReq->lActual, This->m_hEventCancel );
191 LeaveCriticalSection( &This->m_csReader );
200 if ( This->m_bAbortThread )
202 ResetEvent( This->m_hEventCancel );
205 CAsyncReaderImpl_PostReply( This, pReq );
206 SetEvent( This->m_hEventSampQueued );
211 CAsyncReaderImpl_PostRequest( This, pReq );
213 SetEvent( This->m_hEventSampQueued );
218 CAsyncReaderImpl_BeginThread( CAsyncReaderImpl* This )
224 if ( This->m_hEventInit != (HANDLE)NULL ||
225 This->m_hEventCancel != (HANDLE)NULL ||
226 This->m_hEventReqQueued != (HANDLE)NULL ||
227 This->m_hEventSampQueued != (HANDLE)NULL ||
228 This->m_hThread != (HANDLE)NULL )
230 This->m_bAbortThread = FALSE;
232 This->m_hEventInit = CreateEventA(NULL,TRUE,FALSE,NULL);
233 if ( This->m_hEventInit == (HANDLE)NULL )
234 return E_OUTOFMEMORY;
235 This->m_hEventCancel = CreateEventA(NULL,TRUE,FALSE,NULL);
236 if ( This->m_hEventCancel == (HANDLE)NULL )
237 return E_OUTOFMEMORY;
238 This->m_hEventReqQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
239 if ( This->m_hEventReqQueued == (HANDLE)NULL )
240 return E_OUTOFMEMORY;
241 This->m_hEventSampQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
242 if ( This->m_hEventSampQueued == (HANDLE)NULL )
243 return E_OUTOFMEMORY;
245 /* create the processing thread. */
246 This->m_hThread = CreateThread(
248 CAsyncReaderImpl_ThreadEntry,
251 if ( This->m_hThread == (HANDLE)NULL )
254 hEvents[0] = This->m_hEventInit;
255 hEvents[1] = This->m_hThread;
257 dwRes = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
258 if ( dwRes != WAIT_OBJECT_0 )
265 CAsyncReaderImpl_EndThread( CAsyncReaderImpl* This )
267 if ( This->m_hThread != (HANDLE)NULL )
271 This->m_bAbortThread = TRUE;
272 SetEvent( This->m_hEventCancel );
273 if ( WaitForSingleObject( This->m_hThread, 100 ) == WAIT_OBJECT_0 )
276 CloseHandle( This->m_hThread );
277 This->m_hThread = (HANDLE)NULL;
279 if ( This->m_hEventInit != (HANDLE)NULL )
281 CloseHandle( This->m_hEventInit );
282 This->m_hEventInit = (HANDLE)NULL;
284 if ( This->m_hEventCancel != (HANDLE)NULL )
286 CloseHandle( This->m_hEventCancel );
287 This->m_hEventCancel = (HANDLE)NULL;
289 if ( This->m_hEventReqQueued != (HANDLE)NULL )
291 CloseHandle( This->m_hEventReqQueued );
292 This->m_hEventReqQueued = (HANDLE)NULL;
294 if ( This->m_hEventSampQueued != (HANDLE)NULL )
296 CloseHandle( This->m_hEventSampQueued );
297 This->m_hEventSampQueued = (HANDLE)NULL;
301 /***************************************************************************
303 * CAsyncReaderImpl methods
307 static HRESULT WINAPI
308 CAsyncReaderImpl_fnQueryInterface(IAsyncReader* iface,REFIID riid,void** ppobj)
310 ICOM_THIS(CAsyncReaderImpl,iface);
312 TRACE("(%p)->()\n",This);
314 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
318 CAsyncReaderImpl_fnAddRef(IAsyncReader* iface)
320 ICOM_THIS(CAsyncReaderImpl,iface);
322 TRACE("(%p)->()\n",This);
324 return IUnknown_AddRef(This->punkControl);
328 CAsyncReaderImpl_fnRelease(IAsyncReader* iface)
330 ICOM_THIS(CAsyncReaderImpl,iface);
332 TRACE("(%p)->()\n",This);
334 return IUnknown_Release(This->punkControl);
337 static HRESULT WINAPI
338 CAsyncReaderImpl_fnRequestAllocator(IAsyncReader* iface,IMemAllocator* pAlloc,ALLOCATOR_PROPERTIES* pProp,IMemAllocator** ppAllocActual)
340 ICOM_THIS(CAsyncReaderImpl,iface);
342 ALLOCATOR_PROPERTIES propActual;
343 IUnknown* punk = NULL;
345 TRACE("(%p)->(%p,%p,%p)\n",This,pAlloc,pProp,ppAllocActual);
347 if ( pAlloc == NULL || pProp == NULL || ppAllocActual == NULL )
350 IMemAllocator_AddRef(pAlloc);
351 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
354 *ppAllocActual = pAlloc;
357 IMemAllocator_Release(pAlloc);
359 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
362 hr = IUnknown_QueryInterface( punk, &IID_IMemAllocator, (void**)&pAlloc );
363 IUnknown_Release(punk);
367 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
370 *ppAllocActual = pAlloc;
373 IMemAllocator_Release(pAlloc);
378 static HRESULT WINAPI
379 CAsyncReaderImpl_fnRequest(IAsyncReader* iface,IMediaSample* pSample,DWORD_PTR dwContext)
381 ICOM_THIS(CAsyncReaderImpl,iface);
382 HRESULT hr = NOERROR;
383 REFERENCE_TIME rtStart;
384 REFERENCE_TIME rtEnd;
385 AsyncSourceRequest* pReq;
388 TRACE("(%p)->(%p,%u)\n",This,pSample,dwContext);
390 hr = IMediaSample_GetPointer(pSample,&pData);
392 hr = IMediaSample_GetTime(pSample,&rtStart,&rtEnd);
396 pReq = CAsyncReaderImpl_AllocRequest(This);
398 return E_OUTOFMEMORY;
400 pReq->llStart = rtStart / QUARTZ_TIMEUNITS;
401 pReq->lLength = (LONG)(rtEnd / QUARTZ_TIMEUNITS - rtStart / QUARTZ_TIMEUNITS);
404 pReq->pSample = pSample;
405 pReq->dwContext = dwContext;
406 CAsyncReaderImpl_PostRequest( This, pReq );
411 static HRESULT WINAPI
412 CAsyncReaderImpl_fnWaitForNext(IAsyncReader* iface,DWORD dwTimeout,IMediaSample** ppSample,DWORD_PTR* pdwContext)
414 ICOM_THIS(CAsyncReaderImpl,iface);
415 HRESULT hr = NOERROR;
417 AsyncSourceRequest* pReq;
418 REFERENCE_TIME rtStart;
419 REFERENCE_TIME rtEnd;
421 TRACE("(%p)->(%lu,%p,%p)\n",This,dwTimeout,ppSample,pdwContext);
423 EnterCriticalSection( &This->m_csRequest );
424 if ( This->m_bInFlushing )
426 LeaveCriticalSection( &This->m_csRequest );
430 ResetEvent( This->m_hEventSampQueued );
431 pReq = CAsyncReaderImpl_GetReply(This);
434 dwRes = WaitForSingleObject( This->m_hEventSampQueued, dwTimeout );
435 if ( dwRes == WAIT_OBJECT_0 )
436 pReq = CAsyncReaderImpl_GetReply(This);
440 hr = IMediaSample_SetActualDataLength(pReq->pSample,pReq->lActual);
443 rtStart = pReq->llStart * QUARTZ_TIMEUNITS;
444 rtEnd = (pReq->llStart + pReq->lActual) * QUARTZ_TIMEUNITS;
445 hr = IMediaSample_SetTime(pReq->pSample,&rtStart,&rtEnd);
447 *ppSample = pReq->pSample;
448 *pdwContext = pReq->dwContext;
449 if ( hr == S_OK && pReq->lActual != pReq->lLength )
461 static HRESULT WINAPI
462 CAsyncReaderImpl_fnSyncReadAligned(IAsyncReader* iface,IMediaSample* pSample)
464 ICOM_THIS(CAsyncReaderImpl,iface);
466 REFERENCE_TIME rtStart;
467 REFERENCE_TIME rtEnd;
473 TRACE("(%p)->(%p)\n",This,pSample);
475 hr = IMediaSample_GetPointer(pSample,&pData);
477 hr = IMediaSample_GetTime(pSample,&rtStart,&rtEnd);
481 llStart = rtStart / QUARTZ_TIMEUNITS;
482 lLength = (LONG)(rtEnd / QUARTZ_TIMEUNITS - rtStart / QUARTZ_TIMEUNITS);
485 EnterCriticalSection( &This->m_csReader );
486 hr = This->pSource->m_pHandler->pRead( This->pSource, llStart, lLength, pData, &lActual, (HANDLE)NULL );
487 LeaveCriticalSection( &This->m_csReader );
491 hr = IMediaSample_SetActualDataLength(pSample,lActual);
494 rtStart = llStart * QUARTZ_TIMEUNITS;
495 rtEnd = (llStart + lActual) * QUARTZ_TIMEUNITS;
496 hr = IMediaSample_SetTime(pSample,&rtStart,&rtEnd);
498 if ( hr == S_OK && lActual != lLength )
505 static HRESULT WINAPI
506 CAsyncReaderImpl_fnSyncRead(IAsyncReader* iface,LONGLONG llPosStart,LONG lLength,BYTE* pbBuf)
508 ICOM_THIS(CAsyncReaderImpl,iface);
512 TRACE("(%p)->()\n",This);
514 EnterCriticalSection( &This->m_csReader );
515 hr = This->pSource->m_pHandler->pRead( This->pSource, llPosStart, lLength, pbBuf, &lActual, (HANDLE)NULL );
516 LeaveCriticalSection( &This->m_csReader );
518 if ( hr == S_OK && lLength != lActual )
524 static HRESULT WINAPI
525 CAsyncReaderImpl_fnLength(IAsyncReader* iface,LONGLONG* pllTotal,LONGLONG* pllAvailable)
527 ICOM_THIS(CAsyncReaderImpl,iface);
530 TRACE("(%p)->()\n",This);
532 hr = This->pSource->m_pHandler->pGetLength( This->pSource, pllTotal, pllAvailable );
537 static HRESULT WINAPI
538 CAsyncReaderImpl_fnBeginFlush(IAsyncReader* iface)
540 ICOM_THIS(CAsyncReaderImpl,iface);
542 TRACE("(%p)->()\n",This);
544 EnterCriticalSection( &This->m_csRequest );
545 This->m_bInFlushing = TRUE;
546 SetEvent( This->m_hEventCancel );
547 CAsyncReaderImpl_ReleaseReqList(This,This->m_pRequestFirst,FALSE);
548 LeaveCriticalSection( &This->m_csRequest );
553 static HRESULT WINAPI
554 CAsyncReaderImpl_fnEndFlush(IAsyncReader* iface)
556 ICOM_THIS(CAsyncReaderImpl,iface);
558 TRACE("(%p)->()\n",This);
560 EnterCriticalSection( &This->m_csRequest );
561 This->m_bInFlushing = FALSE;
562 ResetEvent( This->m_hEventCancel );
563 LeaveCriticalSection( &This->m_csRequest );
569 static ICOM_VTABLE(IAsyncReader) iasyncreader =
571 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
572 /* IUnknown fields */
573 CAsyncReaderImpl_fnQueryInterface,
574 CAsyncReaderImpl_fnAddRef,
575 CAsyncReaderImpl_fnRelease,
577 /* IAsyncReader fields */
578 CAsyncReaderImpl_fnRequestAllocator,
579 CAsyncReaderImpl_fnRequest,
580 CAsyncReaderImpl_fnWaitForNext,
581 CAsyncReaderImpl_fnSyncReadAligned,
582 CAsyncReaderImpl_fnSyncRead,
583 CAsyncReaderImpl_fnLength,
584 CAsyncReaderImpl_fnBeginFlush,
585 CAsyncReaderImpl_fnEndFlush,
588 HRESULT CAsyncReaderImpl_InitIAsyncReader(
589 CAsyncReaderImpl* This, IUnknown* punkControl,
590 CAsyncSourceImpl* pSource )
592 TRACE("(%p,%p)\n",This,punkControl);
594 if ( punkControl == NULL )
596 ERR( "punkControl must not be NULL\n" );
600 ICOM_VTBL(This) = &iasyncreader;
601 This->punkControl = punkControl;
602 This->pSource = pSource;
603 This->m_bInFlushing = FALSE;
604 This->m_bAbortThread = FALSE;
605 This->m_hEventInit = (HANDLE)NULL;
606 This->m_hEventCancel = (HANDLE)NULL;
607 This->m_hEventReqQueued = (HANDLE)NULL;
608 This->m_hEventSampQueued = (HANDLE)NULL;
609 This->m_hThread = (HANDLE)NULL;
610 This->m_pRequestFirst = NULL;
611 This->m_pReplyFirst = NULL;
612 This->m_pFreeFirst = NULL;
614 InitializeCriticalSection( &This->m_csReader );
615 InitializeCriticalSection( &This->m_csRequest );
616 InitializeCriticalSection( &This->m_csReply );
617 InitializeCriticalSection( &This->m_csFree );
622 void CAsyncReaderImpl_UninitIAsyncReader(
623 CAsyncReaderImpl* This )
625 TRACE("(%p)\n",This);
627 CAsyncReaderImpl_ReleaseReqList(This,This->m_pRequestFirst,TRUE);
628 CAsyncReaderImpl_ReleaseReqList(This,This->m_pReplyFirst,TRUE);
629 CAsyncReaderImpl_ReleaseReqList(This,This->m_pFreeFirst,TRUE);
631 DeleteCriticalSection( &This->m_csReader );
632 DeleteCriticalSection( &This->m_csRequest );
633 DeleteCriticalSection( &This->m_csReply );
634 DeleteCriticalSection( &This->m_csFree );
637 /***************************************************************************
639 * CFileSourceFilterImpl
643 static HRESULT WINAPI
644 CFileSourceFilterImpl_fnQueryInterface(IFileSourceFilter* iface,REFIID riid,void** ppobj)
646 ICOM_THIS(CFileSourceFilterImpl,iface);
648 TRACE("(%p)->()\n",This);
650 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
654 CFileSourceFilterImpl_fnAddRef(IFileSourceFilter* iface)
656 ICOM_THIS(CFileSourceFilterImpl,iface);
658 TRACE("(%p)->()\n",This);
660 return IUnknown_AddRef(This->punkControl);
664 CFileSourceFilterImpl_fnRelease(IFileSourceFilter* iface)
666 ICOM_THIS(CFileSourceFilterImpl,iface);
668 TRACE("(%p)->()\n",This);
670 return IUnknown_Release(This->punkControl);
673 static HRESULT WINAPI
674 CFileSourceFilterImpl_fnLoad(IFileSourceFilter* iface,LPCOLESTR pFileName,const AM_MEDIA_TYPE* pmt)
676 ICOM_THIS(CFileSourceFilterImpl,iface);
679 TRACE("(%p)->(%s,%p)\n",This,debugstr_w(pFileName),pmt);
681 if ( pFileName == NULL )
684 if ( This->m_pwszFileName != NULL )
687 This->m_cbFileName = sizeof(WCHAR)*(lstrlenW(pFileName)+1);
688 This->m_pwszFileName = (WCHAR*)QUARTZ_AllocMem( This->m_cbFileName );
689 if ( This->m_pwszFileName == NULL )
690 return E_OUTOFMEMORY;
691 memcpy( This->m_pwszFileName, pFileName, This->m_cbFileName );
695 hr = QUARTZ_MediaType_Copy( &This->m_mt, pmt );
701 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
702 memcpy( &This->m_mt.majortype, &MEDIATYPE_Stream, sizeof(GUID) );
703 memcpy( &This->m_mt.subtype, &MEDIASUBTYPE_NULL, sizeof(GUID) );
704 This->m_mt.lSampleSize = 1;
705 memcpy( &This->m_mt.formattype, &FORMAT_None, sizeof(GUID) );
708 hr = This->pSource->m_pHandler->pLoad( This->pSource, pFileName );
712 This->pSource->pPin->pin.pmtAcceptTypes = &This->m_mt;
713 This->pSource->pPin->pin.cAcceptTypes = 1;
720 static HRESULT WINAPI
721 CFileSourceFilterImpl_fnGetCurFile(IFileSourceFilter* iface,LPOLESTR* ppFileName,AM_MEDIA_TYPE* pmt)
723 ICOM_THIS(CFileSourceFilterImpl,iface);
724 HRESULT hr = E_NOTIMPL;
726 TRACE("(%p)->(%p,%p)\n",This,ppFileName,pmt);
728 if ( ppFileName == NULL || pmt == NULL )
731 if ( This->m_pwszFileName == NULL )
734 hr = QUARTZ_MediaType_Copy( pmt, &This->m_mt );
738 *ppFileName = (WCHAR*)CoTaskMemAlloc( This->m_cbFileName );
739 if ( *ppFileName == NULL )
741 QUARTZ_MediaType_Free(pmt);
742 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
743 return E_OUTOFMEMORY;
746 memcpy( *ppFileName, This->m_pwszFileName, This->m_cbFileName );
751 static ICOM_VTABLE(IFileSourceFilter) ifilesource =
753 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
754 /* IUnknown fields */
755 CFileSourceFilterImpl_fnQueryInterface,
756 CFileSourceFilterImpl_fnAddRef,
757 CFileSourceFilterImpl_fnRelease,
758 /* IFileSourceFilter fields */
759 CFileSourceFilterImpl_fnLoad,
760 CFileSourceFilterImpl_fnGetCurFile,
763 HRESULT CFileSourceFilterImpl_InitIFileSourceFilter(
764 CFileSourceFilterImpl* This, IUnknown* punkControl,
765 CAsyncSourceImpl* pSource,
766 CRITICAL_SECTION* pcsFileSource )
768 TRACE("(%p,%p)\n",This,punkControl);
770 if ( punkControl == NULL )
772 ERR( "punkControl must not be NULL\n" );
776 ICOM_VTBL(This) = &ifilesource;
777 This->punkControl = punkControl;
778 This->pSource = pSource;
779 This->pcsFileSource = pcsFileSource;
780 This->m_pwszFileName = NULL;
781 This->m_cbFileName = 0;
782 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
787 void CFileSourceFilterImpl_UninitIFileSourceFilter(
788 CFileSourceFilterImpl* This )
790 TRACE("(%p)\n",This);
792 This->pSource->m_pHandler->pCleanup( This->pSource );
793 if ( This->m_pwszFileName != NULL )
794 QUARTZ_FreeMem( This->m_pwszFileName );
795 QUARTZ_MediaType_Free( &This->m_mt );
798 /***************************************************************************
800 * CAsyncSourcePinImpl methods
805 static HRESULT CAsyncSourcePinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
807 CAsyncSourcePinImpl_THIS(pImpl,pin);
809 TRACE("(%p,%p)\n",This,pPin);
811 This->bAsyncReaderQueried = FALSE;
816 static HRESULT CAsyncSourcePinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
818 CAsyncSourcePinImpl_THIS(pImpl,pin);
820 TRACE("(%p,%p)\n",This,pPin);
822 if ( !This->bAsyncReaderQueried )
828 static HRESULT CAsyncSourcePinImpl_OnDisconnect( CPinBaseImpl* pImpl )
830 CAsyncSourcePinImpl_THIS(pImpl,pin);
832 TRACE("(%p)\n",This);
834 This->bAsyncReaderQueried = FALSE;
839 static HRESULT CAsyncSourcePinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
841 CAsyncSourcePinImpl_THIS(pImpl,pin);
843 TRACE("(%p,%p)\n",This,pmt);
847 if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
853 static const CBasePinHandlers outputpinhandlers =
855 CAsyncSourcePinImpl_OnPreConnect, /* pOnPreConnect */
856 CAsyncSourcePinImpl_OnPostConnect, /* pOnPostConnect */
857 CAsyncSourcePinImpl_OnDisconnect, /* pOnDisconnect */
858 CAsyncSourcePinImpl_CheckMediaType, /* pCheckMediaType */
859 NULL, /* pQualityNotify */
861 NULL, /* pReceiveCanBlock */
862 NULL, /* pEndOfStream */
863 NULL, /* pBeginFlush */
864 NULL, /* pEndFlush */
865 NULL, /* pNewSegment */
868 /***************************************************************************
870 * CAsyncSourceImpl methods
874 static HRESULT CAsyncSourceImpl_OnActive( CBaseFilterImpl* pImpl )
876 CAsyncSourceImpl_THIS(pImpl,basefilter);
879 TRACE( "(%p)\n", This );
881 hr = CAsyncReaderImpl_BeginThread(&This->pPin->async);
888 static HRESULT CAsyncSourceImpl_OnInactive( CBaseFilterImpl* pImpl )
890 CAsyncSourceImpl_THIS(pImpl,basefilter);
892 TRACE( "(%p)\n", This );
894 CAsyncReaderImpl_EndThread(&This->pPin->async);
899 static const CBaseFilterHandlers filterhandlers =
901 CAsyncSourceImpl_OnActive, /* pOnActive */
902 CAsyncSourceImpl_OnInactive, /* pOnInactive */
906 /***************************************************************************
908 * new/delete CAsyncSourceImpl
912 /* can I use offsetof safely? - FIXME? */
913 static QUARTZ_IFEntry FilterIFEntries[] =
915 { &IID_IPersist, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
916 { &IID_IMediaFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
917 { &IID_IBaseFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
918 { &IID_IFileSourceFilter, offsetof(CAsyncSourceImpl,filesrc)-offsetof(CAsyncSourceImpl,unk) },
921 static void QUARTZ_DestroyAsyncSource(IUnknown* punk)
923 CAsyncSourceImpl_THIS(punk,unk);
925 TRACE( "(%p)\n", This );
927 if ( This->pPin != NULL )
929 IUnknown_Release(This->pPin->unk.punkControl);
933 This->m_pHandler->pCleanup( This );
935 CFileSourceFilterImpl_UninitIFileSourceFilter(&This->filesrc);
936 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
938 DeleteCriticalSection( &This->csFilter );
941 HRESULT QUARTZ_CreateAsyncSource(
942 IUnknown* punkOuter,void** ppobj,
943 const CLSID* pclsidAsyncSource,
944 LPCWSTR pwszAsyncSourceName,
945 LPCWSTR pwszOutPinName,
946 const AsyncSourceHandlers* pHandler )
948 CAsyncSourceImpl* This = NULL;
951 TRACE("(%p,%p)\n",punkOuter,ppobj);
953 This = (CAsyncSourceImpl*)
954 QUARTZ_AllocObj( sizeof(CAsyncSourceImpl) );
956 return E_OUTOFMEMORY;
959 This->m_pHandler = pHandler;
960 This->m_pUserData = NULL;
962 QUARTZ_IUnkInit( &This->unk, punkOuter );
964 hr = CBaseFilterImpl_InitIBaseFilter(
966 This->unk.punkControl,
972 /* construct this class. */
973 hr = CFileSourceFilterImpl_InitIFileSourceFilter(
974 &This->filesrc, This->unk.punkControl,
975 This, &This->csFilter );
978 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
984 QUARTZ_FreeObj(This);
988 This->unk.pEntries = FilterIFEntries;
989 This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]);
990 This->unk.pOnFinalRelease = QUARTZ_DestroyAsyncSource;
991 InitializeCriticalSection( &This->csFilter );
993 /* create the output pin. */
994 hr = QUARTZ_CreateAsyncSourcePin(
995 This, &This->csFilter,
996 &This->pPin, pwszOutPinName );
998 hr = QUARTZ_CompList_AddComp(
999 This->basefilter.pOutPins,
1000 (IUnknown*)&(This->pPin->pin),
1005 IUnknown_Release( This->unk.punkControl );
1009 *ppobj = (void*)&(This->unk);
1014 /***************************************************************************
1016 * new/delete CAsyncSourcePinImpl
1020 /* can I use offsetof safely? - FIXME? */
1021 static QUARTZ_IFEntry OutPinIFEntries[] =
1023 { &IID_IPin, offsetof(CAsyncSourcePinImpl,pin)-offsetof(CAsyncSourcePinImpl,unk) },
1024 /***{ &IID_IAsyncReader, offsetof(CAsyncSourcePinImpl,async)-offsetof(CAsyncSourcePinImpl,unk) },***/
1027 static HRESULT CAsyncSourceImpl_OnQueryInterface(
1028 IUnknown* punk, const IID* piid, void** ppobj )
1030 CAsyncSourcePinImpl_THIS(punk,unk);
1032 if ( IsEqualGUID( &IID_IAsyncReader, piid ) )
1034 TRACE("IAsyncReader has been queried.\n");
1035 *ppobj = (void*)&This->async;
1036 IUnknown_AddRef(punk);
1037 This->bAsyncReaderQueried = TRUE;
1041 return E_NOINTERFACE;
1044 static void QUARTZ_DestroyAsyncSourcePin(IUnknown* punk)
1046 CAsyncSourcePinImpl_THIS(punk,unk);
1048 TRACE( "(%p)\n", This );
1050 CAsyncReaderImpl_UninitIAsyncReader( &This->async );
1051 CPinBaseImpl_UninitIPin( &This->pin );
1054 HRESULT QUARTZ_CreateAsyncSourcePin(
1055 CAsyncSourceImpl* pFilter,
1056 CRITICAL_SECTION* pcsPin,
1057 CAsyncSourcePinImpl** ppPin,
1058 LPCWSTR pwszPinName )
1060 CAsyncSourcePinImpl* This = NULL;
1063 TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
1065 This = (CAsyncSourcePinImpl*)
1066 QUARTZ_AllocObj( sizeof(CAsyncSourcePinImpl) );
1068 return E_OUTOFMEMORY;
1070 QUARTZ_IUnkInit( &This->unk, NULL );
1071 This->qiext.pNext = NULL;
1072 This->qiext.pOnQueryInterface = &CAsyncSourceImpl_OnQueryInterface;
1073 QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
1075 This->bAsyncReaderQueried = FALSE;
1076 This->pSource = pFilter;
1078 hr = CPinBaseImpl_InitIPin(
1080 This->unk.punkControl,
1082 &pFilter->basefilter,
1085 &outputpinhandlers );
1087 if ( SUCCEEDED(hr) )
1089 hr = CAsyncReaderImpl_InitIAsyncReader(
1091 This->unk.punkControl,
1095 CPinBaseImpl_UninitIPin( &This->pin );
1101 QUARTZ_FreeObj(This);
1105 This->unk.pEntries = OutPinIFEntries;
1106 This->unk.dwEntries = sizeof(OutPinIFEntries)/sizeof(OutPinIFEntries[0]);
1107 This->unk.pOnFinalRelease = QUARTZ_DestroyAsyncSourcePin;
1111 TRACE("returned successfully.\n");
1118 /***************************************************************************
1120 * Implements File Source.
1124 typedef struct AsyncSourceFileImpl
1128 } AsyncSourceFileImpl;
1131 static HRESULT AsyncSourceFileImpl_Load( CAsyncSourceImpl* pImpl, LPCWSTR lpwszSourceName )
1133 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1138 return E_UNEXPECTED;
1139 This = (AsyncSourceFileImpl*)QUARTZ_AllocMem( sizeof(AsyncSourceFileImpl) );
1140 pImpl->m_pUserData = (void*)This;
1142 return E_OUTOFMEMORY;
1143 This->hFile = INVALID_HANDLE_VALUE;
1146 This->hFile = CreateFileW( lpwszSourceName,
1147 GENERIC_READ, FILE_SHARE_READ,
1148 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL );
1149 if ( This->hFile == INVALID_HANDLE_VALUE )
1152 SetLastError(NO_ERROR);
1153 dwLow = GetFileSize( This->hFile, &dwHigh );
1154 if ( dwLow == 0xffffffff && GetLastError() != NO_ERROR )
1157 This->llTotal = (LONGLONG)dwLow | ((LONGLONG)dwHigh << 32);
1162 static HRESULT AsyncSourceFileImpl_Cleanup( CAsyncSourceImpl* pImpl )
1164 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1169 if ( This->hFile != INVALID_HANDLE_VALUE )
1170 CloseHandle(This->hFile);
1172 QUARTZ_FreeMem(This);
1173 pImpl->m_pUserData = NULL;
1178 static HRESULT AsyncSourceFileImpl_GetLength( CAsyncSourceImpl* pImpl, LONGLONG* pllTotal, LONGLONG* pllAvailable )
1180 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1183 return E_UNEXPECTED;
1185 *pllTotal = This->llTotal;
1186 *pllAvailable = This->llTotal;
1191 static HRESULT AsyncSourceFileImpl_Read( CAsyncSourceImpl* pImpl, LONGLONG llOfsStart, LONG lLength, BYTE* pBuf, LONG* plReturned, HANDLE hEventCancel )
1193 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1201 if ( This == NULL || This->hFile == INVALID_HANDLE_VALUE )
1202 return E_UNEXPECTED;
1206 lOfsLow = (LONG)(llOfsStart & 0xffffffff);
1207 lOfsHigh = (LONG)(llOfsStart >> 32);
1208 SetLastError(NO_ERROR);
1209 lOfsLow = SetFilePointer( This->hFile, lOfsLow, &lOfsHigh, FILE_BEGIN );
1210 if ( lOfsLow == (LONG)0xffffffff && GetLastError() != NO_ERROR )
1213 while ( lLength > 0 )
1215 if ( WaitForSingleObject( hEventCancel, 0 ) == WAIT_OBJECT_0 )
1221 lBlock = ( lLength > ASYNCSRC_FILE_BLOCKSIZE ) ?
1222 ASYNCSRC_FILE_BLOCKSIZE : lLength;
1224 if ( !ReadFile(This->hFile,pBuf,(DWORD)lBlock,&dw,NULL) )
1230 lReturned += (LONG)dw;
1231 lLength -= (LONG)dw;
1232 if ( lBlock > (LONG)dw )
1236 *plReturned = lReturned;
1241 static const struct AsyncSourceHandlers asyncsrc_file =
1243 AsyncSourceFileImpl_Load,
1244 AsyncSourceFileImpl_Cleanup,
1245 AsyncSourceFileImpl_GetLength,
1246 AsyncSourceFileImpl_Read,
1249 HRESULT QUARTZ_CreateAsyncReader(IUnknown* punkOuter,void** ppobj)
1251 return QUARTZ_CreateAsyncSource(
1254 QUARTZ_wszAsyncFileSourceName,
1255 QUARTZ_wszAsyncFileSourcePinName,
1259 /***************************************************************************
1261 * Implements URL Source.
1265 typedef struct AsyncSourceURLImpl
1268 } AsyncSourceURLImpl;
1271 static HRESULT AsyncSourceURLImpl_Load( CAsyncSourceImpl* pImpl, LPCWSTR lpwszSourceName )
1273 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1275 FIXME("(%p,%p) stub!\n", pImpl, lpwszSourceName);
1278 return E_UNEXPECTED;
1279 This = (AsyncSourceURLImpl*)QUARTZ_AllocMem( sizeof(AsyncSourceURLImpl) );
1280 pImpl->m_pUserData = (void*)This;
1282 return E_OUTOFMEMORY;
1287 static HRESULT AsyncSourceURLImpl_Cleanup( CAsyncSourceImpl* pImpl )
1289 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1291 FIXME("(%p) stub!\n", This);
1296 QUARTZ_FreeMem(This);
1297 pImpl->m_pUserData = NULL;
1302 static HRESULT AsyncSourceURLImpl_GetLength( CAsyncSourceImpl* pImpl, LONGLONG* pllTotal, LONGLONG* pllAvailable )
1304 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1306 FIXME("(%p,%p,%p) stub!\n", This, pllTotal, pllAvailable);
1309 return E_UNEXPECTED;
1314 static HRESULT AsyncSourceURLImpl_Read( CAsyncSourceImpl* pImpl, LONGLONG llOfsStart, LONG lLength, BYTE* pBuf, LONG* plReturned, HANDLE hEventCancel )
1316 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1318 FIXME("(%p) stub!\n", This);
1321 return E_UNEXPECTED;
1326 static const struct AsyncSourceHandlers asyncsrc_url =
1328 AsyncSourceURLImpl_Load,
1329 AsyncSourceURLImpl_Cleanup,
1330 AsyncSourceURLImpl_GetLength,
1331 AsyncSourceURLImpl_Read,
1335 HRESULT QUARTZ_CreateURLReader(IUnknown* punkOuter,void** ppobj)
1337 return QUARTZ_CreateAsyncSource(
1340 QUARTZ_wszAsyncURLSourceName,
1341 QUARTZ_wszAsyncURLSourcePinName,