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
);
501 if ( lLength
> IMediaSample_GetSize(pSample
) )
503 FIXME("invalid length\n");
507 EnterCriticalSection( &This
->m_csReader
);
508 hr
= This
->pSource
->m_pHandler
->pRead( This
->pSource
, llStart
, lLength
, pData
, &lActual
, (HANDLE
)NULL
);
509 LeaveCriticalSection( &This
->m_csReader
);
513 hr
= IMediaSample_SetActualDataLength(pSample
,lActual
);
516 rtStart
= llStart
* QUARTZ_TIMEUNITS
;
517 rtEnd
= (llStart
+ lActual
) * QUARTZ_TIMEUNITS
;
518 hr
= IMediaSample_SetTime(pSample
,&rtStart
,&rtEnd
);
520 if ( hr
== S_OK
&& lActual
!= lLength
)
527 static HRESULT WINAPI
528 CAsyncReaderImpl_fnSyncRead(IAsyncReader
* iface
,LONGLONG llPosStart
,LONG lLength
,BYTE
* pbBuf
)
530 ICOM_THIS(CAsyncReaderImpl
,iface
);
534 TRACE("(%p)->()\n",This
);
536 EnterCriticalSection( &This
->m_csReader
);
537 hr
= This
->pSource
->m_pHandler
->pRead( This
->pSource
, llPosStart
, lLength
, pbBuf
, &lActual
, (HANDLE
)NULL
);
538 LeaveCriticalSection( &This
->m_csReader
);
540 if ( hr
== S_OK
&& lLength
!= lActual
)
546 static HRESULT WINAPI
547 CAsyncReaderImpl_fnLength(IAsyncReader
* iface
,LONGLONG
* pllTotal
,LONGLONG
* pllAvailable
)
549 ICOM_THIS(CAsyncReaderImpl
,iface
);
552 TRACE("(%p)->()\n",This
);
554 hr
= This
->pSource
->m_pHandler
->pGetLength( This
->pSource
, pllTotal
, pllAvailable
);
559 static HRESULT WINAPI
560 CAsyncReaderImpl_fnBeginFlush(IAsyncReader
* iface
)
562 ICOM_THIS(CAsyncReaderImpl
,iface
);
564 TRACE("(%p)->()\n",This
);
566 EnterCriticalSection( &This
->m_csRequest
);
567 This
->m_bInFlushing
= TRUE
;
568 SetEvent( This
->m_hEventCancel
);
569 CAsyncReaderImpl_ReleaseReqList(This
,&This
->m_pRequestFirst
,FALSE
);
570 LeaveCriticalSection( &This
->m_csRequest
);
575 static HRESULT WINAPI
576 CAsyncReaderImpl_fnEndFlush(IAsyncReader
* iface
)
578 ICOM_THIS(CAsyncReaderImpl
,iface
);
580 TRACE("(%p)->()\n",This
);
582 EnterCriticalSection( &This
->m_csRequest
);
583 This
->m_bInFlushing
= FALSE
;
584 ResetEvent( This
->m_hEventCancel
);
585 LeaveCriticalSection( &This
->m_csRequest
);
591 static ICOM_VTABLE(IAsyncReader
) iasyncreader
=
593 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
594 /* IUnknown fields */
595 CAsyncReaderImpl_fnQueryInterface
,
596 CAsyncReaderImpl_fnAddRef
,
597 CAsyncReaderImpl_fnRelease
,
599 /* IAsyncReader fields */
600 CAsyncReaderImpl_fnRequestAllocator
,
601 CAsyncReaderImpl_fnRequest
,
602 CAsyncReaderImpl_fnWaitForNext
,
603 CAsyncReaderImpl_fnSyncReadAligned
,
604 CAsyncReaderImpl_fnSyncRead
,
605 CAsyncReaderImpl_fnLength
,
606 CAsyncReaderImpl_fnBeginFlush
,
607 CAsyncReaderImpl_fnEndFlush
,
610 HRESULT
CAsyncReaderImpl_InitIAsyncReader(
611 CAsyncReaderImpl
* This
, IUnknown
* punkControl
,
612 CAsyncSourceImpl
* pSource
)
614 TRACE("(%p,%p)\n",This
,punkControl
);
616 if ( punkControl
== NULL
)
618 ERR( "punkControl must not be NULL\n" );
622 ICOM_VTBL(This
) = &iasyncreader
;
623 This
->punkControl
= punkControl
;
624 This
->pSource
= pSource
;
625 This
->m_bInFlushing
= FALSE
;
626 This
->m_bAbortThread
= FALSE
;
627 This
->m_hEventInit
= (HANDLE
)NULL
;
628 This
->m_hEventCancel
= (HANDLE
)NULL
;
629 This
->m_hEventReqQueued
= (HANDLE
)NULL
;
630 This
->m_hEventSampQueued
= (HANDLE
)NULL
;
631 This
->m_hThread
= (HANDLE
)NULL
;
632 This
->m_pRequestFirst
= NULL
;
633 This
->m_pReplyFirst
= NULL
;
634 This
->m_pFreeFirst
= NULL
;
636 InitializeCriticalSection( &This
->m_csReader
);
637 InitializeCriticalSection( &This
->m_csRequest
);
638 InitializeCriticalSection( &This
->m_csReply
);
639 InitializeCriticalSection( &This
->m_csFree
);
644 void CAsyncReaderImpl_UninitIAsyncReader(
645 CAsyncReaderImpl
* This
)
647 TRACE("(%p) enter\n",This
);
649 CAsyncReaderImpl_ReleaseReqList(This
,&This
->m_pRequestFirst
,TRUE
);
650 CAsyncReaderImpl_ReleaseReqList(This
,&This
->m_pReplyFirst
,TRUE
);
651 CAsyncReaderImpl_ReleaseReqList(This
,&This
->m_pFreeFirst
,TRUE
);
653 DeleteCriticalSection( &This
->m_csReader
);
654 DeleteCriticalSection( &This
->m_csRequest
);
655 DeleteCriticalSection( &This
->m_csReply
);
656 DeleteCriticalSection( &This
->m_csFree
);
658 TRACE("(%p) leave\n",This
);
661 /***************************************************************************
663 * CFileSourceFilterImpl
667 static HRESULT WINAPI
668 CFileSourceFilterImpl_fnQueryInterface(IFileSourceFilter
* iface
,REFIID riid
,void** ppobj
)
670 ICOM_THIS(CFileSourceFilterImpl
,iface
);
672 TRACE("(%p)->()\n",This
);
674 return IUnknown_QueryInterface(This
->punkControl
,riid
,ppobj
);
678 CFileSourceFilterImpl_fnAddRef(IFileSourceFilter
* iface
)
680 ICOM_THIS(CFileSourceFilterImpl
,iface
);
682 TRACE("(%p)->()\n",This
);
684 return IUnknown_AddRef(This
->punkControl
);
688 CFileSourceFilterImpl_fnRelease(IFileSourceFilter
* iface
)
690 ICOM_THIS(CFileSourceFilterImpl
,iface
);
692 TRACE("(%p)->()\n",This
);
694 return IUnknown_Release(This
->punkControl
);
697 static HRESULT WINAPI
698 CFileSourceFilterImpl_fnLoad(IFileSourceFilter
* iface
,LPCOLESTR pFileName
,const AM_MEDIA_TYPE
* pmt
)
700 ICOM_THIS(CFileSourceFilterImpl
,iface
);
703 TRACE("(%p)->(%s,%p)\n",This
,debugstr_w(pFileName
),pmt
);
705 if ( pFileName
== NULL
)
708 if ( This
->m_pwszFileName
!= NULL
)
711 This
->m_cbFileName
= sizeof(WCHAR
)*(lstrlenW(pFileName
)+1);
712 This
->m_pwszFileName
= (WCHAR
*)QUARTZ_AllocMem( This
->m_cbFileName
);
713 if ( This
->m_pwszFileName
== NULL
)
714 return E_OUTOFMEMORY
;
715 memcpy( This
->m_pwszFileName
, pFileName
, This
->m_cbFileName
);
719 hr
= QUARTZ_MediaType_Copy( &This
->m_mt
, pmt
);
725 ZeroMemory( &This
->m_mt
, sizeof(AM_MEDIA_TYPE
) );
726 memcpy( &This
->m_mt
.majortype
, &MEDIATYPE_Stream
, sizeof(GUID
) );
727 memcpy( &This
->m_mt
.subtype
, &MEDIASUBTYPE_NULL
, sizeof(GUID
) );
728 This
->m_mt
.lSampleSize
= 1;
729 memcpy( &This
->m_mt
.formattype
, &FORMAT_None
, sizeof(GUID
) );
732 hr
= This
->pSource
->m_pHandler
->pLoad( This
->pSource
, pFileName
);
736 This
->pSource
->pPin
->pin
.pmtAcceptTypes
= &This
->m_mt
;
737 This
->pSource
->pPin
->pin
.cAcceptTypes
= 1;
744 static HRESULT WINAPI
745 CFileSourceFilterImpl_fnGetCurFile(IFileSourceFilter
* iface
,LPOLESTR
* ppFileName
,AM_MEDIA_TYPE
* pmt
)
747 ICOM_THIS(CFileSourceFilterImpl
,iface
);
748 HRESULT hr
= E_NOTIMPL
;
750 TRACE("(%p)->(%p,%p)\n",This
,ppFileName
,pmt
);
752 if ( ppFileName
== NULL
|| pmt
== NULL
)
755 if ( This
->m_pwszFileName
== NULL
)
758 hr
= QUARTZ_MediaType_Copy( pmt
, &This
->m_mt
);
762 *ppFileName
= (WCHAR
*)CoTaskMemAlloc( This
->m_cbFileName
);
763 if ( *ppFileName
== NULL
)
765 QUARTZ_MediaType_Free(pmt
);
766 ZeroMemory( pmt
, sizeof(AM_MEDIA_TYPE
) );
767 return E_OUTOFMEMORY
;
770 memcpy( *ppFileName
, This
->m_pwszFileName
, This
->m_cbFileName
);
775 static ICOM_VTABLE(IFileSourceFilter
) ifilesource
=
777 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
778 /* IUnknown fields */
779 CFileSourceFilterImpl_fnQueryInterface
,
780 CFileSourceFilterImpl_fnAddRef
,
781 CFileSourceFilterImpl_fnRelease
,
782 /* IFileSourceFilter fields */
783 CFileSourceFilterImpl_fnLoad
,
784 CFileSourceFilterImpl_fnGetCurFile
,
787 HRESULT
CFileSourceFilterImpl_InitIFileSourceFilter(
788 CFileSourceFilterImpl
* This
, IUnknown
* punkControl
,
789 CAsyncSourceImpl
* pSource
,
790 CRITICAL_SECTION
* pcsFileSource
)
792 TRACE("(%p,%p)\n",This
,punkControl
);
794 if ( punkControl
== NULL
)
796 ERR( "punkControl must not be NULL\n" );
800 ICOM_VTBL(This
) = &ifilesource
;
801 This
->punkControl
= punkControl
;
802 This
->pSource
= pSource
;
803 This
->pcsFileSource
= pcsFileSource
;
804 This
->m_pwszFileName
= NULL
;
805 This
->m_cbFileName
= 0;
806 ZeroMemory( &This
->m_mt
, sizeof(AM_MEDIA_TYPE
) );
811 void CFileSourceFilterImpl_UninitIFileSourceFilter(
812 CFileSourceFilterImpl
* This
)
814 TRACE("(%p)\n",This
);
816 This
->pSource
->m_pHandler
->pCleanup( This
->pSource
);
817 if ( This
->m_pwszFileName
!= NULL
)
818 QUARTZ_FreeMem( This
->m_pwszFileName
);
819 QUARTZ_MediaType_Free( &This
->m_mt
);
822 /***************************************************************************
824 * CAsyncSourcePinImpl methods
829 static HRESULT
CAsyncSourcePinImpl_OnPreConnect( CPinBaseImpl
* pImpl
, IPin
* pPin
)
831 CAsyncSourcePinImpl_THIS(pImpl
,pin
);
833 TRACE("(%p,%p)\n",This
,pPin
);
835 This
->bAsyncReaderQueried
= FALSE
;
840 static HRESULT
CAsyncSourcePinImpl_OnPostConnect( CPinBaseImpl
* pImpl
, IPin
* pPin
)
842 CAsyncSourcePinImpl_THIS(pImpl
,pin
);
844 TRACE("(%p,%p)\n",This
,pPin
);
846 if ( !This
->bAsyncReaderQueried
)
852 static HRESULT
CAsyncSourcePinImpl_OnDisconnect( CPinBaseImpl
* pImpl
)
854 CAsyncSourcePinImpl_THIS(pImpl
,pin
);
856 TRACE("(%p)\n",This
);
858 This
->bAsyncReaderQueried
= FALSE
;
863 static HRESULT
CAsyncSourcePinImpl_CheckMediaType( CPinBaseImpl
* pImpl
, const AM_MEDIA_TYPE
* pmt
)
865 CAsyncSourcePinImpl_THIS(pImpl
,pin
);
867 TRACE("(%p,%p)\n",This
,pmt
);
871 if ( !IsEqualGUID( &pmt
->majortype
, &MEDIATYPE_Stream
) )
877 static const CBasePinHandlers outputpinhandlers
=
879 CAsyncSourcePinImpl_OnPreConnect
, /* pOnPreConnect */
880 CAsyncSourcePinImpl_OnPostConnect
, /* pOnPostConnect */
881 CAsyncSourcePinImpl_OnDisconnect
, /* pOnDisconnect */
882 CAsyncSourcePinImpl_CheckMediaType
, /* pCheckMediaType */
883 NULL
, /* pQualityNotify */
885 NULL
, /* pReceiveCanBlock */
886 NULL
, /* pEndOfStream */
887 NULL
, /* pBeginFlush */
888 NULL
, /* pEndFlush */
889 NULL
, /* pNewSegment */
892 /***************************************************************************
894 * CAsyncSourceImpl methods
898 static HRESULT
CAsyncSourceImpl_OnActive( CBaseFilterImpl
* pImpl
)
900 CAsyncSourceImpl_THIS(pImpl
,basefilter
);
903 TRACE( "(%p)\n", This
);
905 hr
= CAsyncReaderImpl_BeginThread(&This
->pPin
->async
);
912 static HRESULT
CAsyncSourceImpl_OnInactive( CBaseFilterImpl
* pImpl
)
914 CAsyncSourceImpl_THIS(pImpl
,basefilter
);
916 TRACE( "(%p)\n", This
);
918 CAsyncReaderImpl_EndThread(&This
->pPin
->async
);
923 static const CBaseFilterHandlers filterhandlers
=
925 CAsyncSourceImpl_OnActive
, /* pOnActive */
926 CAsyncSourceImpl_OnInactive
, /* pOnInactive */
930 /***************************************************************************
932 * new/delete CAsyncSourceImpl
936 /* can I use offsetof safely? - FIXME? */
937 static QUARTZ_IFEntry FilterIFEntries
[] =
939 { &IID_IPersist
, offsetof(CAsyncSourceImpl
,basefilter
)-offsetof(CAsyncSourceImpl
,unk
) },
940 { &IID_IMediaFilter
, offsetof(CAsyncSourceImpl
,basefilter
)-offsetof(CAsyncSourceImpl
,unk
) },
941 { &IID_IBaseFilter
, offsetof(CAsyncSourceImpl
,basefilter
)-offsetof(CAsyncSourceImpl
,unk
) },
942 { &IID_IFileSourceFilter
, offsetof(CAsyncSourceImpl
,filesrc
)-offsetof(CAsyncSourceImpl
,unk
) },
945 static void QUARTZ_DestroyAsyncSource(IUnknown
* punk
)
947 CAsyncSourceImpl_THIS(punk
,unk
);
949 TRACE( "(%p)\n", This
);
951 if ( This
->pPin
!= NULL
)
953 IUnknown_Release(This
->pPin
->unk
.punkControl
);
957 This
->m_pHandler
->pCleanup( This
);
959 CFileSourceFilterImpl_UninitIFileSourceFilter(&This
->filesrc
);
960 CBaseFilterImpl_UninitIBaseFilter(&This
->basefilter
);
962 DeleteCriticalSection( &This
->csFilter
);
965 HRESULT
QUARTZ_CreateAsyncSource(
966 IUnknown
* punkOuter
,void** ppobj
,
967 const CLSID
* pclsidAsyncSource
,
968 LPCWSTR pwszAsyncSourceName
,
969 LPCWSTR pwszOutPinName
,
970 const AsyncSourceHandlers
* pHandler
)
972 CAsyncSourceImpl
* This
= NULL
;
975 TRACE("(%p,%p)\n",punkOuter
,ppobj
);
977 This
= (CAsyncSourceImpl
*)
978 QUARTZ_AllocObj( sizeof(CAsyncSourceImpl
) );
980 return E_OUTOFMEMORY
;
983 This
->m_pHandler
= pHandler
;
984 This
->m_pUserData
= NULL
;
986 QUARTZ_IUnkInit( &This
->unk
, punkOuter
);
988 hr
= CBaseFilterImpl_InitIBaseFilter(
990 This
->unk
.punkControl
,
996 /* construct this class. */
997 hr
= CFileSourceFilterImpl_InitIFileSourceFilter(
998 &This
->filesrc
, This
->unk
.punkControl
,
999 This
, &This
->csFilter
);
1002 CBaseFilterImpl_UninitIBaseFilter(&This
->basefilter
);
1008 QUARTZ_FreeObj(This
);
1012 This
->unk
.pEntries
= FilterIFEntries
;
1013 This
->unk
.dwEntries
= sizeof(FilterIFEntries
)/sizeof(FilterIFEntries
[0]);
1014 This
->unk
.pOnFinalRelease
= QUARTZ_DestroyAsyncSource
;
1015 InitializeCriticalSection( &This
->csFilter
);
1017 /* create the output pin. */
1018 hr
= QUARTZ_CreateAsyncSourcePin(
1019 This
, &This
->csFilter
,
1020 &This
->pPin
, pwszOutPinName
);
1021 if ( SUCCEEDED(hr
) )
1022 hr
= QUARTZ_CompList_AddComp(
1023 This
->basefilter
.pOutPins
,
1024 (IUnknown
*)&(This
->pPin
->pin
),
1029 IUnknown_Release( This
->unk
.punkControl
);
1033 *ppobj
= (void*)&(This
->unk
);
1038 /***************************************************************************
1040 * new/delete CAsyncSourcePinImpl
1044 /* can I use offsetof safely? - FIXME? */
1045 static QUARTZ_IFEntry OutPinIFEntries
[] =
1047 { &IID_IPin
, offsetof(CAsyncSourcePinImpl
,pin
)-offsetof(CAsyncSourcePinImpl
,unk
) },
1048 /***{ &IID_IAsyncReader, offsetof(CAsyncSourcePinImpl,async)-offsetof(CAsyncSourcePinImpl,unk) },***/
1051 static HRESULT
CAsyncSourceImpl_OnQueryInterface(
1052 IUnknown
* punk
, const IID
* piid
, void** ppobj
)
1054 CAsyncSourcePinImpl_THIS(punk
,unk
);
1056 if ( IsEqualGUID( &IID_IAsyncReader
, piid
) )
1058 TRACE("IAsyncReader has been queried.\n");
1059 *ppobj
= (void*)&This
->async
;
1060 IUnknown_AddRef(punk
);
1061 This
->bAsyncReaderQueried
= TRUE
;
1065 return E_NOINTERFACE
;
1068 static void QUARTZ_DestroyAsyncSourcePin(IUnknown
* punk
)
1070 CAsyncSourcePinImpl_THIS(punk
,unk
);
1072 TRACE( "(%p)\n", This
);
1074 CAsyncReaderImpl_UninitIAsyncReader( &This
->async
);
1075 CPinBaseImpl_UninitIPin( &This
->pin
);
1078 HRESULT
QUARTZ_CreateAsyncSourcePin(
1079 CAsyncSourceImpl
* pFilter
,
1080 CRITICAL_SECTION
* pcsPin
,
1081 CAsyncSourcePinImpl
** ppPin
,
1082 LPCWSTR pwszPinName
)
1084 CAsyncSourcePinImpl
* This
= NULL
;
1087 TRACE("(%p,%p,%p)\n",pFilter
,pcsPin
,ppPin
);
1089 This
= (CAsyncSourcePinImpl
*)
1090 QUARTZ_AllocObj( sizeof(CAsyncSourcePinImpl
) );
1092 return E_OUTOFMEMORY
;
1094 QUARTZ_IUnkInit( &This
->unk
, NULL
);
1095 This
->qiext
.pNext
= NULL
;
1096 This
->qiext
.pOnQueryInterface
= &CAsyncSourceImpl_OnQueryInterface
;
1097 QUARTZ_IUnkAddDelegation( &This
->unk
, &This
->qiext
);
1099 This
->bAsyncReaderQueried
= FALSE
;
1100 This
->pSource
= pFilter
;
1102 hr
= CPinBaseImpl_InitIPin(
1104 This
->unk
.punkControl
,
1106 &pFilter
->basefilter
,
1109 &outputpinhandlers
);
1111 if ( SUCCEEDED(hr
) )
1113 hr
= CAsyncReaderImpl_InitIAsyncReader(
1115 This
->unk
.punkControl
,
1119 CPinBaseImpl_UninitIPin( &This
->pin
);
1125 QUARTZ_FreeObj(This
);
1129 This
->unk
.pEntries
= OutPinIFEntries
;
1130 This
->unk
.dwEntries
= sizeof(OutPinIFEntries
)/sizeof(OutPinIFEntries
[0]);
1131 This
->unk
.pOnFinalRelease
= QUARTZ_DestroyAsyncSourcePin
;
1135 TRACE("returned successfully.\n");
1142 /***************************************************************************
1144 * Implements File Source.
1148 typedef struct AsyncSourceFileImpl
1152 } AsyncSourceFileImpl
;
1155 static HRESULT
AsyncSourceFileImpl_Load( CAsyncSourceImpl
* pImpl
, LPCWSTR lpwszSourceName
)
1157 AsyncSourceFileImpl
* This
= (AsyncSourceFileImpl
*)pImpl
->m_pUserData
;
1162 return E_UNEXPECTED
;
1163 This
= (AsyncSourceFileImpl
*)QUARTZ_AllocMem( sizeof(AsyncSourceFileImpl
) );
1164 pImpl
->m_pUserData
= (void*)This
;
1166 return E_OUTOFMEMORY
;
1167 This
->hFile
= INVALID_HANDLE_VALUE
;
1170 This
->hFile
= CreateFileW( lpwszSourceName
,
1171 GENERIC_READ
, FILE_SHARE_READ
,
1172 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, (HANDLE
)NULL
);
1173 if ( This
->hFile
== INVALID_HANDLE_VALUE
)
1176 SetLastError(NO_ERROR
);
1177 dwLow
= GetFileSize( This
->hFile
, &dwHigh
);
1178 if ( dwLow
== 0xffffffff && GetLastError() != NO_ERROR
)
1181 This
->llTotal
= (LONGLONG
)dwLow
| ((LONGLONG
)dwHigh
<< 32);
1186 static HRESULT
AsyncSourceFileImpl_Cleanup( CAsyncSourceImpl
* pImpl
)
1188 AsyncSourceFileImpl
* This
= (AsyncSourceFileImpl
*)pImpl
->m_pUserData
;
1193 if ( This
->hFile
!= INVALID_HANDLE_VALUE
)
1194 CloseHandle(This
->hFile
);
1196 QUARTZ_FreeMem(This
);
1197 pImpl
->m_pUserData
= NULL
;
1202 static HRESULT
AsyncSourceFileImpl_GetLength( CAsyncSourceImpl
* pImpl
, LONGLONG
* pllTotal
, LONGLONG
* pllAvailable
)
1204 AsyncSourceFileImpl
* This
= (AsyncSourceFileImpl
*)pImpl
->m_pUserData
;
1207 return E_UNEXPECTED
;
1209 *pllTotal
= This
->llTotal
;
1210 *pllAvailable
= This
->llTotal
;
1215 static HRESULT
AsyncSourceFileImpl_Read( CAsyncSourceImpl
* pImpl
, LONGLONG llOfsStart
, LONG lLength
, BYTE
* pBuf
, LONG
* plReturned
, HANDLE hEventCancel
)
1217 AsyncSourceFileImpl
* This
= (AsyncSourceFileImpl
*)pImpl
->m_pUserData
;
1225 if ( This
== NULL
|| This
->hFile
== INVALID_HANDLE_VALUE
)
1226 return E_UNEXPECTED
;
1230 lOfsLow
= (LONG
)(llOfsStart
& 0xffffffff);
1231 lOfsHigh
= (LONG
)(llOfsStart
>> 32);
1232 SetLastError(NO_ERROR
);
1233 lOfsLow
= SetFilePointer( This
->hFile
, lOfsLow
, &lOfsHigh
, FILE_BEGIN
);
1234 if ( lOfsLow
== (LONG
)0xffffffff && GetLastError() != NO_ERROR
)
1237 while ( lLength
> 0 )
1239 if ( hEventCancel
!= (HANDLE
)NULL
&&
1240 WaitForSingleObject( hEventCancel
, 0 ) == WAIT_OBJECT_0
)
1246 lBlock
= ( lLength
> ASYNCSRC_FILE_BLOCKSIZE
) ?
1247 ASYNCSRC_FILE_BLOCKSIZE
: lLength
;
1249 if ( !ReadFile(This
->hFile
,pBuf
,(DWORD
)lBlock
,&dw
,NULL
) )
1255 lReturned
+= (LONG
)dw
;
1256 lLength
-= (LONG
)dw
;
1257 if ( lBlock
> (LONG
)dw
)
1261 *plReturned
= lReturned
;
1266 static const struct AsyncSourceHandlers asyncsrc_file
=
1268 AsyncSourceFileImpl_Load
,
1269 AsyncSourceFileImpl_Cleanup
,
1270 AsyncSourceFileImpl_GetLength
,
1271 AsyncSourceFileImpl_Read
,
1274 HRESULT
QUARTZ_CreateAsyncReader(IUnknown
* punkOuter
,void** ppobj
)
1276 return QUARTZ_CreateAsyncSource(
1279 QUARTZ_wszAsyncFileSourceName
,
1280 QUARTZ_wszAsyncFileSourcePinName
,
1284 /***************************************************************************
1286 * Implements URL Source.
1290 typedef struct AsyncSourceURLImpl
1293 } AsyncSourceURLImpl
;
1296 static HRESULT
AsyncSourceURLImpl_Load( CAsyncSourceImpl
* pImpl
, LPCWSTR lpwszSourceName
)
1298 AsyncSourceURLImpl
* This
= (AsyncSourceURLImpl
*)pImpl
->m_pUserData
;
1300 FIXME("(%p,%p) stub!\n", pImpl
, lpwszSourceName
);
1303 return E_UNEXPECTED
;
1304 This
= (AsyncSourceURLImpl
*)QUARTZ_AllocMem( sizeof(AsyncSourceURLImpl
) );
1305 pImpl
->m_pUserData
= (void*)This
;
1307 return E_OUTOFMEMORY
;
1312 static HRESULT
AsyncSourceURLImpl_Cleanup( CAsyncSourceImpl
* pImpl
)
1314 AsyncSourceURLImpl
* This
= (AsyncSourceURLImpl
*)pImpl
->m_pUserData
;
1316 FIXME("(%p) stub!\n", This
);
1321 QUARTZ_FreeMem(This
);
1322 pImpl
->m_pUserData
= NULL
;
1327 static HRESULT
AsyncSourceURLImpl_GetLength( CAsyncSourceImpl
* pImpl
, LONGLONG
* pllTotal
, LONGLONG
* pllAvailable
)
1329 AsyncSourceURLImpl
* This
= (AsyncSourceURLImpl
*)pImpl
->m_pUserData
;
1331 FIXME("(%p,%p,%p) stub!\n", This
, pllTotal
, pllAvailable
);
1334 return E_UNEXPECTED
;
1339 static HRESULT
AsyncSourceURLImpl_Read( CAsyncSourceImpl
* pImpl
, LONGLONG llOfsStart
, LONG lLength
, BYTE
* pBuf
, LONG
* plReturned
, HANDLE hEventCancel
)
1341 AsyncSourceURLImpl
* This
= (AsyncSourceURLImpl
*)pImpl
->m_pUserData
;
1343 FIXME("(%p) stub!\n", This
);
1346 return E_UNEXPECTED
;
1351 static const struct AsyncSourceHandlers asyncsrc_url
=
1353 AsyncSourceURLImpl_Load
,
1354 AsyncSourceURLImpl_Cleanup
,
1355 AsyncSourceURLImpl_GetLength
,
1356 AsyncSourceURLImpl_Read
,
1360 HRESULT
QUARTZ_CreateURLReader(IUnknown
* punkOuter
,void** ppobj
)
1362 return QUARTZ_CreateAsyncSource(
1365 QUARTZ_wszAsyncURLSourceName
,
1366 QUARTZ_wszAsyncURLSourcePinName
,