2 * Implements Asynchronous File/URL Source.
4 * FIXME - URL source is not implemented yet.
6 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
37 #include "quartz_private.h"
43 const WCHAR QUARTZ_wszAsyncFileSourceName[] =
44 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','A','s','y','n','c','.',')',0};
45 const WCHAR QUARTZ_wszAsyncFileSourcePinName[] =
47 const WCHAR QUARTZ_wszAsyncURLSourceName[] =
48 {'F','i','l','e',' ','S','o','u','r','c','e',' ','(','U','R','L',')',0};
49 const WCHAR QUARTZ_wszAsyncURLSourcePinName[] =
54 /***************************************************************************
56 * CAsyncReaderImpl internal methods
61 AsyncSourceRequest* CAsyncReaderImpl_AllocRequest( CAsyncReaderImpl* This )
63 AsyncSourceRequest* pReq;
65 EnterCriticalSection( &This->m_csFree );
66 pReq = This->m_pFreeFirst;
68 This->m_pFreeFirst = pReq->pNext;
69 LeaveCriticalSection( &This->m_csFree );
73 pReq = (AsyncSourceRequest*)QUARTZ_AllocMem(
74 sizeof(AsyncSourceRequest) );
91 void CAsyncReaderImpl_FreeRequest( CAsyncReaderImpl* This, AsyncSourceRequest* pReq, BOOL bReleaseMem )
95 EnterCriticalSection( &This->m_csFree );
96 pReq->pNext = This->m_pFreeFirst;
97 This->m_pFreeFirst = pReq;
98 LeaveCriticalSection( &This->m_csFree );
102 QUARTZ_FreeMem( pReq );
107 AsyncSourceRequest* CAsyncReaderImpl_GetRequest( CAsyncReaderImpl* This )
109 AsyncSourceRequest* pReq;
111 EnterCriticalSection( &This->m_csRequest );
112 pReq = This->m_pRequestFirst;
114 This->m_pRequestFirst = pReq->pNext;
115 LeaveCriticalSection( &This->m_csRequest );
121 AsyncSourceRequest* CAsyncReaderImpl_GetReply( CAsyncReaderImpl* This )
123 AsyncSourceRequest* pReq;
125 EnterCriticalSection( &This->m_csReply );
126 pReq = This->m_pReplyFirst;
128 This->m_pReplyFirst = pReq->pNext;
129 LeaveCriticalSection( &This->m_csReply );
135 void CAsyncReaderImpl_PostRequest( CAsyncReaderImpl* This, AsyncSourceRequest* pReq )
137 /* FIXME - add to tail */
138 EnterCriticalSection( &This->m_csRequest );
139 pReq->pNext = This->m_pRequestFirst;
140 This->m_pRequestFirst = pReq;
141 if ( This->m_hEventReqQueued != (HANDLE)NULL )
142 SetEvent( This->m_hEventReqQueued );
143 LeaveCriticalSection( &This->m_csRequest );
147 void CAsyncReaderImpl_PostReply( CAsyncReaderImpl* This, AsyncSourceRequest* pReq )
149 /* FIXME - add to tail */
150 EnterCriticalSection( &This->m_csReply );
151 pReq->pNext = This->m_pReplyFirst;
152 This->m_pReplyFirst = pReq;
153 if ( This->m_hEventSampQueued != (HANDLE)NULL )
154 SetEvent( This->m_hEventSampQueued );
155 LeaveCriticalSection( &This->m_csReply );
159 void CAsyncReaderImpl_ReleaseReqList( CAsyncReaderImpl* This, AsyncSourceRequest** ppReq, BOOL bReleaseMem )
161 AsyncSourceRequest* pReq;
162 AsyncSourceRequest* pReqNext;
164 TRACE("(%p,%p,%d)\n",This,*ppReq,bReleaseMem);
165 pReq = *ppReq; *ppReq = NULL;
166 while ( pReq != NULL )
168 pReqNext = pReq->pNext;
169 CAsyncReaderImpl_FreeRequest(This,pReq,bReleaseMem);
175 CAsyncReaderImpl_ThreadEntry( LPVOID pv )
177 CAsyncReaderImpl* This = (CAsyncReaderImpl*)pv;
178 HANDLE hWaitEvents[2];
181 AsyncSourceRequest* pReq = NULL;
183 SetEvent( This->m_hEventInit );
185 hWaitEvents[0] = This->m_hEventReqQueued;
186 hWaitEvents[1] = This->m_hEventCancel;
188 TRACE("enter message loop.\n");
192 ResetEvent( This->m_hEventReqQueued );
193 pReq = CAsyncReaderImpl_GetRequest(This);
196 dwRes = WaitForMultipleObjects(2,hWaitEvents,FALSE,INFINITE);
197 if ( dwRes != WAIT_OBJECT_0 )
199 if ( This->m_bAbortThread )
205 /* process a queued request */
206 EnterCriticalSection( &This->m_csReader );
207 hr = This->pSource->m_pHandler->pRead( This->pSource, pReq->llStart, pReq->lLength, pReq->pBuf, &pReq->lActual, This->m_hEventCancel );
208 LeaveCriticalSection( &This->m_csReader );
217 if ( This->m_bAbortThread )
219 ResetEvent( This->m_hEventCancel );
222 CAsyncReaderImpl_PostReply( This, pReq );
223 SetEvent( This->m_hEventSampQueued );
228 CAsyncReaderImpl_PostRequest( This, pReq );
230 SetEvent( This->m_hEventSampQueued );
235 CAsyncReaderImpl_BeginThread( CAsyncReaderImpl* This )
241 if ( This->m_hEventInit != (HANDLE)NULL ||
242 This->m_hEventCancel != (HANDLE)NULL ||
243 This->m_hEventReqQueued != (HANDLE)NULL ||
244 This->m_hEventSampQueued != (HANDLE)NULL ||
245 This->m_hThread != (HANDLE)NULL )
247 This->m_bAbortThread = FALSE;
249 This->m_hEventInit = CreateEventA(NULL,TRUE,FALSE,NULL);
250 if ( This->m_hEventInit == (HANDLE)NULL )
251 return E_OUTOFMEMORY;
252 This->m_hEventCancel = CreateEventA(NULL,TRUE,FALSE,NULL);
253 if ( This->m_hEventCancel == (HANDLE)NULL )
254 return E_OUTOFMEMORY;
255 This->m_hEventReqQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
256 if ( This->m_hEventReqQueued == (HANDLE)NULL )
257 return E_OUTOFMEMORY;
258 This->m_hEventSampQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
259 if ( This->m_hEventSampQueued == (HANDLE)NULL )
260 return E_OUTOFMEMORY;
262 /* create the processing thread. */
263 This->m_hThread = CreateThread(
265 CAsyncReaderImpl_ThreadEntry,
268 if ( This->m_hThread == (HANDLE)NULL )
271 hEvents[0] = This->m_hEventInit;
272 hEvents[1] = This->m_hThread;
274 dwRes = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
275 if ( dwRes != WAIT_OBJECT_0 )
282 CAsyncReaderImpl_EndThread( CAsyncReaderImpl* This )
284 if ( This->m_hThread != (HANDLE)NULL )
288 This->m_bAbortThread = TRUE;
289 SetEvent( This->m_hEventCancel );
290 if ( WaitForSingleObject( This->m_hThread, 100 ) == WAIT_OBJECT_0 )
293 CloseHandle( This->m_hThread );
294 This->m_hThread = (HANDLE)NULL;
296 if ( This->m_hEventInit != (HANDLE)NULL )
298 CloseHandle( This->m_hEventInit );
299 This->m_hEventInit = (HANDLE)NULL;
301 if ( This->m_hEventCancel != (HANDLE)NULL )
303 CloseHandle( This->m_hEventCancel );
304 This->m_hEventCancel = (HANDLE)NULL;
306 if ( This->m_hEventReqQueued != (HANDLE)NULL )
308 CloseHandle( This->m_hEventReqQueued );
309 This->m_hEventReqQueued = (HANDLE)NULL;
311 if ( This->m_hEventSampQueued != (HANDLE)NULL )
313 CloseHandle( This->m_hEventSampQueued );
314 This->m_hEventSampQueued = (HANDLE)NULL;
318 /***************************************************************************
320 * CAsyncReaderImpl methods
324 static HRESULT WINAPI
325 CAsyncReaderImpl_fnQueryInterface(IAsyncReader* iface,REFIID riid,void** ppobj)
327 ICOM_THIS(CAsyncReaderImpl,iface);
329 TRACE("(%p)->()\n",This);
331 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
335 CAsyncReaderImpl_fnAddRef(IAsyncReader* iface)
337 ICOM_THIS(CAsyncReaderImpl,iface);
339 TRACE("(%p)->()\n",This);
341 return IUnknown_AddRef(This->punkControl);
345 CAsyncReaderImpl_fnRelease(IAsyncReader* iface)
347 ICOM_THIS(CAsyncReaderImpl,iface);
349 TRACE("(%p)->()\n",This);
351 return IUnknown_Release(This->punkControl);
354 static HRESULT WINAPI
355 CAsyncReaderImpl_fnRequestAllocator(IAsyncReader* iface,IMemAllocator* pAlloc,ALLOCATOR_PROPERTIES* pProp,IMemAllocator** ppAllocActual)
357 ICOM_THIS(CAsyncReaderImpl,iface);
359 ALLOCATOR_PROPERTIES propActual;
360 IUnknown* punk = NULL;
362 TRACE("(%p)->(%p,%p,%p)\n",This,pAlloc,pProp,ppAllocActual);
364 if ( pAlloc == NULL || pProp == NULL || ppAllocActual == NULL )
367 IMemAllocator_AddRef(pAlloc);
368 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
371 *ppAllocActual = pAlloc;
374 IMemAllocator_Release(pAlloc);
376 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
379 hr = IUnknown_QueryInterface( punk, &IID_IMemAllocator, (void**)&pAlloc );
380 IUnknown_Release(punk);
384 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
387 *ppAllocActual = pAlloc;
390 IMemAllocator_Release(pAlloc);
395 static HRESULT WINAPI
396 CAsyncReaderImpl_fnRequest(IAsyncReader* iface,IMediaSample* pSample,DWORD_PTR dwContext)
398 ICOM_THIS(CAsyncReaderImpl,iface);
399 HRESULT hr = NOERROR;
400 REFERENCE_TIME rtStart;
401 REFERENCE_TIME rtEnd;
402 AsyncSourceRequest* pReq;
405 TRACE("(%p)->(%p,%u)\n",This,pSample,dwContext);
407 hr = IMediaSample_GetPointer(pSample,&pData);
409 hr = IMediaSample_GetTime(pSample,&rtStart,&rtEnd);
413 pReq = CAsyncReaderImpl_AllocRequest(This);
415 return E_OUTOFMEMORY;
417 pReq->llStart = rtStart / QUARTZ_TIMEUNITS;
418 pReq->lLength = (LONG)(rtEnd / QUARTZ_TIMEUNITS - rtStart / QUARTZ_TIMEUNITS);
421 pReq->pSample = pSample;
422 pReq->dwContext = dwContext;
423 CAsyncReaderImpl_PostRequest( This, pReq );
428 static HRESULT WINAPI
429 CAsyncReaderImpl_fnWaitForNext(IAsyncReader* iface,DWORD dwTimeout,IMediaSample** ppSample,DWORD_PTR* pdwContext)
431 ICOM_THIS(CAsyncReaderImpl,iface);
432 HRESULT hr = NOERROR;
434 AsyncSourceRequest* pReq;
435 REFERENCE_TIME rtStart;
436 REFERENCE_TIME rtEnd;
438 TRACE("(%p)->(%lu,%p,%p)\n",This,dwTimeout,ppSample,pdwContext);
440 EnterCriticalSection( &This->m_csRequest );
441 if ( This->m_bInFlushing )
443 LeaveCriticalSection( &This->m_csRequest );
447 ResetEvent( This->m_hEventSampQueued );
448 pReq = CAsyncReaderImpl_GetReply(This);
451 dwRes = WaitForSingleObject( This->m_hEventSampQueued, dwTimeout );
452 if ( dwRes == WAIT_OBJECT_0 )
453 pReq = CAsyncReaderImpl_GetReply(This);
457 hr = IMediaSample_SetActualDataLength(pReq->pSample,pReq->lActual);
460 rtStart = pReq->llStart * QUARTZ_TIMEUNITS;
461 rtEnd = (pReq->llStart + pReq->lActual) * QUARTZ_TIMEUNITS;
462 hr = IMediaSample_SetTime(pReq->pSample,&rtStart,&rtEnd);
464 *ppSample = pReq->pSample;
465 *pdwContext = pReq->dwContext;
466 if ( hr == S_OK && pReq->lActual != pReq->lLength )
478 static HRESULT WINAPI
479 CAsyncReaderImpl_fnSyncReadAligned(IAsyncReader* iface,IMediaSample* pSample)
481 ICOM_THIS(CAsyncReaderImpl,iface);
483 REFERENCE_TIME rtStart;
484 REFERENCE_TIME rtEnd;
490 TRACE("(%p)->(%p)\n",This,pSample);
492 hr = IMediaSample_GetPointer(pSample,&pData);
494 hr = IMediaSample_GetTime(pSample,&rtStart,&rtEnd);
498 llStart = rtStart / QUARTZ_TIMEUNITS;
499 lLength = (LONG)(rtEnd / QUARTZ_TIMEUNITS - rtStart / QUARTZ_TIMEUNITS);
502 EnterCriticalSection( &This->m_csReader );
503 hr = This->pSource->m_pHandler->pRead( This->pSource, llStart, lLength, pData, &lActual, (HANDLE)NULL );
504 LeaveCriticalSection( &This->m_csReader );
508 hr = IMediaSample_SetActualDataLength(pSample,lActual);
511 rtStart = llStart * QUARTZ_TIMEUNITS;
512 rtEnd = (llStart + lActual) * QUARTZ_TIMEUNITS;
513 hr = IMediaSample_SetTime(pSample,&rtStart,&rtEnd);
515 if ( hr == S_OK && lActual != lLength )
522 static HRESULT WINAPI
523 CAsyncReaderImpl_fnSyncRead(IAsyncReader* iface,LONGLONG llPosStart,LONG lLength,BYTE* pbBuf)
525 ICOM_THIS(CAsyncReaderImpl,iface);
529 TRACE("(%p)->()\n",This);
531 EnterCriticalSection( &This->m_csReader );
532 hr = This->pSource->m_pHandler->pRead( This->pSource, llPosStart, lLength, pbBuf, &lActual, (HANDLE)NULL );
533 LeaveCriticalSection( &This->m_csReader );
535 if ( hr == S_OK && lLength != lActual )
541 static HRESULT WINAPI
542 CAsyncReaderImpl_fnLength(IAsyncReader* iface,LONGLONG* pllTotal,LONGLONG* pllAvailable)
544 ICOM_THIS(CAsyncReaderImpl,iface);
547 TRACE("(%p)->()\n",This);
549 hr = This->pSource->m_pHandler->pGetLength( This->pSource, pllTotal, pllAvailable );
554 static HRESULT WINAPI
555 CAsyncReaderImpl_fnBeginFlush(IAsyncReader* iface)
557 ICOM_THIS(CAsyncReaderImpl,iface);
559 TRACE("(%p)->()\n",This);
561 EnterCriticalSection( &This->m_csRequest );
562 This->m_bInFlushing = TRUE;
563 SetEvent( This->m_hEventCancel );
564 CAsyncReaderImpl_ReleaseReqList(This,&This->m_pRequestFirst,FALSE);
565 LeaveCriticalSection( &This->m_csRequest );
570 static HRESULT WINAPI
571 CAsyncReaderImpl_fnEndFlush(IAsyncReader* iface)
573 ICOM_THIS(CAsyncReaderImpl,iface);
575 TRACE("(%p)->()\n",This);
577 EnterCriticalSection( &This->m_csRequest );
578 This->m_bInFlushing = FALSE;
579 ResetEvent( This->m_hEventCancel );
580 LeaveCriticalSection( &This->m_csRequest );
586 static ICOM_VTABLE(IAsyncReader) iasyncreader =
588 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
589 /* IUnknown fields */
590 CAsyncReaderImpl_fnQueryInterface,
591 CAsyncReaderImpl_fnAddRef,
592 CAsyncReaderImpl_fnRelease,
594 /* IAsyncReader fields */
595 CAsyncReaderImpl_fnRequestAllocator,
596 CAsyncReaderImpl_fnRequest,
597 CAsyncReaderImpl_fnWaitForNext,
598 CAsyncReaderImpl_fnSyncReadAligned,
599 CAsyncReaderImpl_fnSyncRead,
600 CAsyncReaderImpl_fnLength,
601 CAsyncReaderImpl_fnBeginFlush,
602 CAsyncReaderImpl_fnEndFlush,
605 HRESULT CAsyncReaderImpl_InitIAsyncReader(
606 CAsyncReaderImpl* This, IUnknown* punkControl,
607 CAsyncSourceImpl* pSource )
609 TRACE("(%p,%p)\n",This,punkControl);
611 if ( punkControl == NULL )
613 ERR( "punkControl must not be NULL\n" );
617 ICOM_VTBL(This) = &iasyncreader;
618 This->punkControl = punkControl;
619 This->pSource = pSource;
620 This->m_bInFlushing = FALSE;
621 This->m_bAbortThread = FALSE;
622 This->m_hEventInit = (HANDLE)NULL;
623 This->m_hEventCancel = (HANDLE)NULL;
624 This->m_hEventReqQueued = (HANDLE)NULL;
625 This->m_hEventSampQueued = (HANDLE)NULL;
626 This->m_hThread = (HANDLE)NULL;
627 This->m_pRequestFirst = NULL;
628 This->m_pReplyFirst = NULL;
629 This->m_pFreeFirst = NULL;
631 InitializeCriticalSection( &This->m_csReader );
632 InitializeCriticalSection( &This->m_csRequest );
633 InitializeCriticalSection( &This->m_csReply );
634 InitializeCriticalSection( &This->m_csFree );
639 void CAsyncReaderImpl_UninitIAsyncReader(
640 CAsyncReaderImpl* This )
642 TRACE("(%p) enter\n",This);
644 CAsyncReaderImpl_ReleaseReqList(This,&This->m_pRequestFirst,TRUE);
645 CAsyncReaderImpl_ReleaseReqList(This,&This->m_pReplyFirst,TRUE);
646 CAsyncReaderImpl_ReleaseReqList(This,&This->m_pFreeFirst,TRUE);
648 DeleteCriticalSection( &This->m_csReader );
649 DeleteCriticalSection( &This->m_csRequest );
650 DeleteCriticalSection( &This->m_csReply );
651 DeleteCriticalSection( &This->m_csFree );
653 TRACE("(%p) leave\n",This);
656 /***************************************************************************
658 * CFileSourceFilterImpl
662 static HRESULT WINAPI
663 CFileSourceFilterImpl_fnQueryInterface(IFileSourceFilter* iface,REFIID riid,void** ppobj)
665 ICOM_THIS(CFileSourceFilterImpl,iface);
667 TRACE("(%p)->()\n",This);
669 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
673 CFileSourceFilterImpl_fnAddRef(IFileSourceFilter* iface)
675 ICOM_THIS(CFileSourceFilterImpl,iface);
677 TRACE("(%p)->()\n",This);
679 return IUnknown_AddRef(This->punkControl);
683 CFileSourceFilterImpl_fnRelease(IFileSourceFilter* iface)
685 ICOM_THIS(CFileSourceFilterImpl,iface);
687 TRACE("(%p)->()\n",This);
689 return IUnknown_Release(This->punkControl);
692 static HRESULT WINAPI
693 CFileSourceFilterImpl_fnLoad(IFileSourceFilter* iface,LPCOLESTR pFileName,const AM_MEDIA_TYPE* pmt)
695 ICOM_THIS(CFileSourceFilterImpl,iface);
698 TRACE("(%p)->(%s,%p)\n",This,debugstr_w(pFileName),pmt);
700 if ( pFileName == NULL )
703 if ( This->m_pwszFileName != NULL )
706 This->m_cbFileName = sizeof(WCHAR)*(lstrlenW(pFileName)+1);
707 This->m_pwszFileName = (WCHAR*)QUARTZ_AllocMem( This->m_cbFileName );
708 if ( This->m_pwszFileName == NULL )
709 return E_OUTOFMEMORY;
710 memcpy( This->m_pwszFileName, pFileName, This->m_cbFileName );
714 hr = QUARTZ_MediaType_Copy( &This->m_mt, pmt );
720 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
721 memcpy( &This->m_mt.majortype, &MEDIATYPE_Stream, sizeof(GUID) );
722 memcpy( &This->m_mt.subtype, &MEDIASUBTYPE_NULL, sizeof(GUID) );
723 This->m_mt.lSampleSize = 1;
724 memcpy( &This->m_mt.formattype, &FORMAT_None, sizeof(GUID) );
727 hr = This->pSource->m_pHandler->pLoad( This->pSource, pFileName );
731 This->pSource->pPin->pin.pmtAcceptTypes = &This->m_mt;
732 This->pSource->pPin->pin.cAcceptTypes = 1;
739 static HRESULT WINAPI
740 CFileSourceFilterImpl_fnGetCurFile(IFileSourceFilter* iface,LPOLESTR* ppFileName,AM_MEDIA_TYPE* pmt)
742 ICOM_THIS(CFileSourceFilterImpl,iface);
743 HRESULT hr = E_NOTIMPL;
745 TRACE("(%p)->(%p,%p)\n",This,ppFileName,pmt);
747 if ( ppFileName == NULL || pmt == NULL )
750 if ( This->m_pwszFileName == NULL )
753 hr = QUARTZ_MediaType_Copy( pmt, &This->m_mt );
757 *ppFileName = (WCHAR*)CoTaskMemAlloc( This->m_cbFileName );
758 if ( *ppFileName == NULL )
760 QUARTZ_MediaType_Free(pmt);
761 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
762 return E_OUTOFMEMORY;
765 memcpy( *ppFileName, This->m_pwszFileName, This->m_cbFileName );
770 static ICOM_VTABLE(IFileSourceFilter) ifilesource =
772 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
773 /* IUnknown fields */
774 CFileSourceFilterImpl_fnQueryInterface,
775 CFileSourceFilterImpl_fnAddRef,
776 CFileSourceFilterImpl_fnRelease,
777 /* IFileSourceFilter fields */
778 CFileSourceFilterImpl_fnLoad,
779 CFileSourceFilterImpl_fnGetCurFile,
782 HRESULT CFileSourceFilterImpl_InitIFileSourceFilter(
783 CFileSourceFilterImpl* This, IUnknown* punkControl,
784 CAsyncSourceImpl* pSource,
785 CRITICAL_SECTION* pcsFileSource )
787 TRACE("(%p,%p)\n",This,punkControl);
789 if ( punkControl == NULL )
791 ERR( "punkControl must not be NULL\n" );
795 ICOM_VTBL(This) = &ifilesource;
796 This->punkControl = punkControl;
797 This->pSource = pSource;
798 This->pcsFileSource = pcsFileSource;
799 This->m_pwszFileName = NULL;
800 This->m_cbFileName = 0;
801 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
806 void CFileSourceFilterImpl_UninitIFileSourceFilter(
807 CFileSourceFilterImpl* This )
809 TRACE("(%p)\n",This);
811 This->pSource->m_pHandler->pCleanup( This->pSource );
812 if ( This->m_pwszFileName != NULL )
813 QUARTZ_FreeMem( This->m_pwszFileName );
814 QUARTZ_MediaType_Free( &This->m_mt );
817 /***************************************************************************
819 * CAsyncSourcePinImpl methods
824 static HRESULT CAsyncSourcePinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
826 CAsyncSourcePinImpl_THIS(pImpl,pin);
828 TRACE("(%p,%p)\n",This,pPin);
830 This->bAsyncReaderQueried = FALSE;
835 static HRESULT CAsyncSourcePinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
837 CAsyncSourcePinImpl_THIS(pImpl,pin);
839 TRACE("(%p,%p)\n",This,pPin);
841 if ( !This->bAsyncReaderQueried )
847 static HRESULT CAsyncSourcePinImpl_OnDisconnect( CPinBaseImpl* pImpl )
849 CAsyncSourcePinImpl_THIS(pImpl,pin);
851 TRACE("(%p)\n",This);
853 This->bAsyncReaderQueried = FALSE;
858 static HRESULT CAsyncSourcePinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
860 CAsyncSourcePinImpl_THIS(pImpl,pin);
862 TRACE("(%p,%p)\n",This,pmt);
866 if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
872 static const CBasePinHandlers outputpinhandlers =
874 CAsyncSourcePinImpl_OnPreConnect, /* pOnPreConnect */
875 CAsyncSourcePinImpl_OnPostConnect, /* pOnPostConnect */
876 CAsyncSourcePinImpl_OnDisconnect, /* pOnDisconnect */
877 CAsyncSourcePinImpl_CheckMediaType, /* pCheckMediaType */
878 NULL, /* pQualityNotify */
880 NULL, /* pReceiveCanBlock */
881 NULL, /* pEndOfStream */
882 NULL, /* pBeginFlush */
883 NULL, /* pEndFlush */
884 NULL, /* pNewSegment */
887 /***************************************************************************
889 * CAsyncSourceImpl methods
893 static HRESULT CAsyncSourceImpl_OnActive( CBaseFilterImpl* pImpl )
895 CAsyncSourceImpl_THIS(pImpl,basefilter);
898 TRACE( "(%p)\n", This );
900 hr = CAsyncReaderImpl_BeginThread(&This->pPin->async);
907 static HRESULT CAsyncSourceImpl_OnInactive( CBaseFilterImpl* pImpl )
909 CAsyncSourceImpl_THIS(pImpl,basefilter);
911 TRACE( "(%p)\n", This );
913 CAsyncReaderImpl_EndThread(&This->pPin->async);
918 static const CBaseFilterHandlers filterhandlers =
920 CAsyncSourceImpl_OnActive, /* pOnActive */
921 CAsyncSourceImpl_OnInactive, /* pOnInactive */
925 /***************************************************************************
927 * new/delete CAsyncSourceImpl
931 /* can I use offsetof safely? - FIXME? */
932 static QUARTZ_IFEntry FilterIFEntries[] =
934 { &IID_IPersist, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
935 { &IID_IMediaFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
936 { &IID_IBaseFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
937 { &IID_IFileSourceFilter, offsetof(CAsyncSourceImpl,filesrc)-offsetof(CAsyncSourceImpl,unk) },
940 static void QUARTZ_DestroyAsyncSource(IUnknown* punk)
942 CAsyncSourceImpl_THIS(punk,unk);
944 TRACE( "(%p)\n", This );
946 if ( This->pPin != NULL )
948 IUnknown_Release(This->pPin->unk.punkControl);
952 This->m_pHandler->pCleanup( This );
954 CFileSourceFilterImpl_UninitIFileSourceFilter(&This->filesrc);
955 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
957 DeleteCriticalSection( &This->csFilter );
960 HRESULT QUARTZ_CreateAsyncSource(
961 IUnknown* punkOuter,void** ppobj,
962 const CLSID* pclsidAsyncSource,
963 LPCWSTR pwszAsyncSourceName,
964 LPCWSTR pwszOutPinName,
965 const AsyncSourceHandlers* pHandler )
967 CAsyncSourceImpl* This = NULL;
970 TRACE("(%p,%p)\n",punkOuter,ppobj);
972 This = (CAsyncSourceImpl*)
973 QUARTZ_AllocObj( sizeof(CAsyncSourceImpl) );
975 return E_OUTOFMEMORY;
978 This->m_pHandler = pHandler;
979 This->m_pUserData = NULL;
981 QUARTZ_IUnkInit( &This->unk, punkOuter );
983 hr = CBaseFilterImpl_InitIBaseFilter(
985 This->unk.punkControl,
991 /* construct this class. */
992 hr = CFileSourceFilterImpl_InitIFileSourceFilter(
993 &This->filesrc, This->unk.punkControl,
994 This, &This->csFilter );
997 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
1003 QUARTZ_FreeObj(This);
1007 This->unk.pEntries = FilterIFEntries;
1008 This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]);
1009 This->unk.pOnFinalRelease = QUARTZ_DestroyAsyncSource;
1010 InitializeCriticalSection( &This->csFilter );
1012 /* create the output pin. */
1013 hr = QUARTZ_CreateAsyncSourcePin(
1014 This, &This->csFilter,
1015 &This->pPin, pwszOutPinName );
1016 if ( SUCCEEDED(hr) )
1017 hr = QUARTZ_CompList_AddComp(
1018 This->basefilter.pOutPins,
1019 (IUnknown*)&(This->pPin->pin),
1024 IUnknown_Release( This->unk.punkControl );
1028 *ppobj = (void*)&(This->unk);
1033 /***************************************************************************
1035 * new/delete CAsyncSourcePinImpl
1039 /* can I use offsetof safely? - FIXME? */
1040 static QUARTZ_IFEntry OutPinIFEntries[] =
1042 { &IID_IPin, offsetof(CAsyncSourcePinImpl,pin)-offsetof(CAsyncSourcePinImpl,unk) },
1043 /***{ &IID_IAsyncReader, offsetof(CAsyncSourcePinImpl,async)-offsetof(CAsyncSourcePinImpl,unk) },***/
1046 static HRESULT CAsyncSourceImpl_OnQueryInterface(
1047 IUnknown* punk, const IID* piid, void** ppobj )
1049 CAsyncSourcePinImpl_THIS(punk,unk);
1051 if ( IsEqualGUID( &IID_IAsyncReader, piid ) )
1053 TRACE("IAsyncReader has been queried.\n");
1054 *ppobj = (void*)&This->async;
1055 IUnknown_AddRef(punk);
1056 This->bAsyncReaderQueried = TRUE;
1060 return E_NOINTERFACE;
1063 static void QUARTZ_DestroyAsyncSourcePin(IUnknown* punk)
1065 CAsyncSourcePinImpl_THIS(punk,unk);
1067 TRACE( "(%p)\n", This );
1069 CAsyncReaderImpl_UninitIAsyncReader( &This->async );
1070 CPinBaseImpl_UninitIPin( &This->pin );
1073 HRESULT QUARTZ_CreateAsyncSourcePin(
1074 CAsyncSourceImpl* pFilter,
1075 CRITICAL_SECTION* pcsPin,
1076 CAsyncSourcePinImpl** ppPin,
1077 LPCWSTR pwszPinName )
1079 CAsyncSourcePinImpl* This = NULL;
1082 TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
1084 This = (CAsyncSourcePinImpl*)
1085 QUARTZ_AllocObj( sizeof(CAsyncSourcePinImpl) );
1087 return E_OUTOFMEMORY;
1089 QUARTZ_IUnkInit( &This->unk, NULL );
1090 This->qiext.pNext = NULL;
1091 This->qiext.pOnQueryInterface = &CAsyncSourceImpl_OnQueryInterface;
1092 QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
1094 This->bAsyncReaderQueried = FALSE;
1095 This->pSource = pFilter;
1097 hr = CPinBaseImpl_InitIPin(
1099 This->unk.punkControl,
1101 &pFilter->basefilter,
1104 &outputpinhandlers );
1106 if ( SUCCEEDED(hr) )
1108 hr = CAsyncReaderImpl_InitIAsyncReader(
1110 This->unk.punkControl,
1114 CPinBaseImpl_UninitIPin( &This->pin );
1120 QUARTZ_FreeObj(This);
1124 This->unk.pEntries = OutPinIFEntries;
1125 This->unk.dwEntries = sizeof(OutPinIFEntries)/sizeof(OutPinIFEntries[0]);
1126 This->unk.pOnFinalRelease = QUARTZ_DestroyAsyncSourcePin;
1130 TRACE("returned successfully.\n");
1137 /***************************************************************************
1139 * Implements File Source.
1143 typedef struct AsyncSourceFileImpl
1147 } AsyncSourceFileImpl;
1150 static HRESULT AsyncSourceFileImpl_Load( CAsyncSourceImpl* pImpl, LPCWSTR lpwszSourceName )
1152 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1157 return E_UNEXPECTED;
1158 This = (AsyncSourceFileImpl*)QUARTZ_AllocMem( sizeof(AsyncSourceFileImpl) );
1159 pImpl->m_pUserData = (void*)This;
1161 return E_OUTOFMEMORY;
1162 This->hFile = INVALID_HANDLE_VALUE;
1165 This->hFile = CreateFileW( lpwszSourceName,
1166 GENERIC_READ, FILE_SHARE_READ,
1167 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL );
1168 if ( This->hFile == INVALID_HANDLE_VALUE )
1171 SetLastError(NO_ERROR);
1172 dwLow = GetFileSize( This->hFile, &dwHigh );
1173 if ( dwLow == 0xffffffff && GetLastError() != NO_ERROR )
1176 This->llTotal = (LONGLONG)dwLow | ((LONGLONG)dwHigh << 32);
1181 static HRESULT AsyncSourceFileImpl_Cleanup( CAsyncSourceImpl* pImpl )
1183 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1188 if ( This->hFile != INVALID_HANDLE_VALUE )
1189 CloseHandle(This->hFile);
1191 QUARTZ_FreeMem(This);
1192 pImpl->m_pUserData = NULL;
1197 static HRESULT AsyncSourceFileImpl_GetLength( CAsyncSourceImpl* pImpl, LONGLONG* pllTotal, LONGLONG* pllAvailable )
1199 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1202 return E_UNEXPECTED;
1204 *pllTotal = This->llTotal;
1205 *pllAvailable = This->llTotal;
1210 static HRESULT AsyncSourceFileImpl_Read( CAsyncSourceImpl* pImpl, LONGLONG llOfsStart, LONG lLength, BYTE* pBuf, LONG* plReturned, HANDLE hEventCancel )
1212 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1220 if ( This == NULL || This->hFile == INVALID_HANDLE_VALUE )
1221 return E_UNEXPECTED;
1225 lOfsLow = (LONG)(llOfsStart & 0xffffffff);
1226 lOfsHigh = (LONG)(llOfsStart >> 32);
1227 SetLastError(NO_ERROR);
1228 lOfsLow = SetFilePointer( This->hFile, lOfsLow, &lOfsHigh, FILE_BEGIN );
1229 if ( lOfsLow == (LONG)0xffffffff && GetLastError() != NO_ERROR )
1232 while ( lLength > 0 )
1234 if ( hEventCancel != (HANDLE)NULL &&
1235 WaitForSingleObject( hEventCancel, 0 ) == WAIT_OBJECT_0 )
1241 lBlock = ( lLength > ASYNCSRC_FILE_BLOCKSIZE ) ?
1242 ASYNCSRC_FILE_BLOCKSIZE : lLength;
1244 if ( !ReadFile(This->hFile,pBuf,(DWORD)lBlock,&dw,NULL) )
1250 lReturned += (LONG)dw;
1251 lLength -= (LONG)dw;
1252 if ( lBlock > (LONG)dw )
1256 *plReturned = lReturned;
1261 static const struct AsyncSourceHandlers asyncsrc_file =
1263 AsyncSourceFileImpl_Load,
1264 AsyncSourceFileImpl_Cleanup,
1265 AsyncSourceFileImpl_GetLength,
1266 AsyncSourceFileImpl_Read,
1269 HRESULT QUARTZ_CreateAsyncReader(IUnknown* punkOuter,void** ppobj)
1271 return QUARTZ_CreateAsyncSource(
1274 QUARTZ_wszAsyncFileSourceName,
1275 QUARTZ_wszAsyncFileSourcePinName,
1279 /***************************************************************************
1281 * Implements URL Source.
1285 typedef struct AsyncSourceURLImpl
1288 } AsyncSourceURLImpl;
1291 static HRESULT AsyncSourceURLImpl_Load( CAsyncSourceImpl* pImpl, LPCWSTR lpwszSourceName )
1293 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1295 FIXME("(%p,%p) stub!\n", pImpl, lpwszSourceName);
1298 return E_UNEXPECTED;
1299 This = (AsyncSourceURLImpl*)QUARTZ_AllocMem( sizeof(AsyncSourceURLImpl) );
1300 pImpl->m_pUserData = (void*)This;
1302 return E_OUTOFMEMORY;
1307 static HRESULT AsyncSourceURLImpl_Cleanup( CAsyncSourceImpl* pImpl )
1309 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1311 FIXME("(%p) stub!\n", This);
1316 QUARTZ_FreeMem(This);
1317 pImpl->m_pUserData = NULL;
1322 static HRESULT AsyncSourceURLImpl_GetLength( CAsyncSourceImpl* pImpl, LONGLONG* pllTotal, LONGLONG* pllAvailable )
1324 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1326 FIXME("(%p,%p,%p) stub!\n", This, pllTotal, pllAvailable);
1329 return E_UNEXPECTED;
1334 static HRESULT AsyncSourceURLImpl_Read( CAsyncSourceImpl* pImpl, LONGLONG llOfsStart, LONG lLength, BYTE* pBuf, LONG* plReturned, HANDLE hEventCancel )
1336 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1338 FIXME("(%p) stub!\n", This);
1341 return E_UNEXPECTED;
1346 static const struct AsyncSourceHandlers asyncsrc_url =
1348 AsyncSourceURLImpl_Load,
1349 AsyncSourceURLImpl_Cleanup,
1350 AsyncSourceURLImpl_GetLength,
1351 AsyncSourceURLImpl_Read,
1355 HRESULT QUARTZ_CreateURLReader(IUnknown* punkOuter,void** ppobj)
1357 return QUARTZ_CreateAsyncSource(
1360 QUARTZ_wszAsyncURLSourceName,
1361 QUARTZ_wszAsyncURLSourcePinName,