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
,