2 * Implements Asynchronous File/URL Source.
4 * FIXME - not work yet.
6 * hidenori@a2.ctktv.ne.jp
16 #include "wine/obj_base.h"
21 #include "debugtools.h"
22 DEFAULT_DEBUG_CHANNEL(quartz);
24 #include "quartz_private.h"
29 /***************************************************************************
31 * CAsyncReaderImpl internal methods
36 CAsyncReaderImpl_ThreadEntry( LPVOID pv )
38 CAsyncReaderImpl* This = (CAsyncReaderImpl*)pv;
39 HANDLE hWaitEvents[2];
40 HANDLE hReadEvents[2];
43 SetEvent( This->m_hEventInit );
45 hWaitEvents[0] = This->m_hEventReqQueued;
46 hWaitEvents[1] = This->m_hEventAbort;
48 hReadEvents[0] = This->m_hEventSampQueued;
49 hReadEvents[1] = This->m_hEventAbort;
53 dwRes = WaitForMultipleObjects(2,hWaitEvents,FALSE,INFINITE);
54 if ( dwRes != WAIT_OBJECT_0 )
57 /* FIXME - process a queued request */
59 dwRes = WaitForMultipleObjects(2,hReadEvents,FALSE,INFINITE);
60 if ( dwRes != WAIT_OBJECT_0 )
68 CAsyncReaderImpl_BeginThread( CAsyncReaderImpl* This )
74 if ( This->m_hEventInit != (HANDLE)NULL ||
75 This->m_hEventAbort != (HANDLE)NULL ||
76 This->m_hEventReqQueued != (HANDLE)NULL ||
77 This->m_hEventSampQueued != (HANDLE)NULL ||
78 This->m_hEventCompletion != (HANDLE)NULL ||
79 This->m_hThread != (HANDLE)NULL )
82 This->m_hEventInit = CreateEventA(NULL,TRUE,FALSE,NULL);
83 if ( This->m_hEventInit == (HANDLE)NULL )
85 This->m_hEventAbort = CreateEventA(NULL,TRUE,FALSE,NULL);
86 if ( This->m_hEventAbort == (HANDLE)NULL )
88 This->m_hEventReqQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
89 if ( This->m_hEventReqQueued == (HANDLE)NULL )
91 This->m_hEventSampQueued = CreateEventA(NULL,TRUE,FALSE,NULL);
92 if ( This->m_hEventSampQueued == (HANDLE)NULL )
94 This->m_hEventCompletion = CreateEventA(NULL,TRUE,FALSE,NULL);
95 if ( This->m_hEventCompletion == (HANDLE)NULL )
98 /* create the processing thread. */
99 This->m_hThread = CreateThread(
101 CAsyncReaderImpl_ThreadEntry,
104 if ( This->m_hThread == (HANDLE)NULL )
107 hEvents[0] = This->m_hEventInit;
108 hEvents[1] = This->m_hThread;
110 dwRes = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
111 if ( dwRes != WAIT_OBJECT_0 )
118 CAsyncReaderImpl_EndThread( CAsyncReaderImpl* This )
120 if ( This->m_hThread != (HANDLE)NULL )
122 SetEvent( This->m_hEventAbort );
124 WaitForSingleObject( This->m_hThread, INFINITE );
125 CloseHandle( This->m_hThread );
126 This->m_hThread = (HANDLE)NULL;
128 if ( This->m_hEventInit != (HANDLE)NULL )
130 CloseHandle( This->m_hEventInit );
131 This->m_hEventInit = (HANDLE)NULL;
133 if ( This->m_hEventAbort != (HANDLE)NULL )
135 CloseHandle( This->m_hEventAbort );
136 This->m_hEventAbort = (HANDLE)NULL;
138 if ( This->m_hEventReqQueued != (HANDLE)NULL )
140 CloseHandle( This->m_hEventReqQueued );
141 This->m_hEventReqQueued = (HANDLE)NULL;
143 if ( This->m_hEventSampQueued != (HANDLE)NULL )
145 CloseHandle( This->m_hEventSampQueued );
146 This->m_hEventSampQueued = (HANDLE)NULL;
148 if ( This->m_hEventCompletion != (HANDLE)NULL )
150 CloseHandle( This->m_hEventCompletion );
151 This->m_hEventCompletion = (HANDLE)NULL;
155 /***************************************************************************
157 * CAsyncReaderImpl methods
161 static HRESULT WINAPI
162 CAsyncReaderImpl_fnQueryInterface(IAsyncReader* iface,REFIID riid,void** ppobj)
164 ICOM_THIS(CAsyncReaderImpl,iface);
166 TRACE("(%p)->()\n",This);
168 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
172 CAsyncReaderImpl_fnAddRef(IAsyncReader* iface)
174 ICOM_THIS(CAsyncReaderImpl,iface);
176 TRACE("(%p)->()\n",This);
178 return IUnknown_AddRef(This->punkControl);
182 CAsyncReaderImpl_fnRelease(IAsyncReader* iface)
184 ICOM_THIS(CAsyncReaderImpl,iface);
186 TRACE("(%p)->()\n",This);
188 return IUnknown_Release(This->punkControl);
191 static HRESULT WINAPI
192 CAsyncReaderImpl_fnRequestAllocator(IAsyncReader* iface,IMemAllocator* pAlloc,ALLOCATOR_PROPERTIES* pProp,IMemAllocator** ppAllocActual)
194 ICOM_THIS(CAsyncReaderImpl,iface);
196 ALLOCATOR_PROPERTIES propActual;
197 IUnknown* punk = NULL;
199 TRACE("(%p)->(%p,%p,%p)\n",This,pAlloc,pProp,ppAllocActual);
201 if ( pAlloc == NULL || pProp == NULL || ppAllocActual == NULL )
204 IMemAllocator_AddRef(pAlloc);
205 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
208 *ppAllocActual = pAlloc;
211 IMemAllocator_Release(pAlloc);
213 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
216 hr = IUnknown_QueryInterface( punk, &IID_IMemAllocator, (void**)&pAlloc );
217 IUnknown_Release(punk);
221 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
224 *ppAllocActual = pAlloc;
227 IMemAllocator_Release(pAlloc);
232 static HRESULT WINAPI
233 CAsyncReaderImpl_fnRequest(IAsyncReader* iface,IMediaSample* pSample,DWORD_PTR dwContext)
235 ICOM_THIS(CAsyncReaderImpl,iface);
237 FIXME("(%p)->() stub!\n",This);
239 EnterCriticalSection( This->pcsReader );
240 LeaveCriticalSection( This->pcsReader );
245 static HRESULT WINAPI
246 CAsyncReaderImpl_fnWaitForNext(IAsyncReader* iface,DWORD dwTimeout,IMediaSample** pSample,DWORD_PTR* pdwContext)
248 ICOM_THIS(CAsyncReaderImpl,iface);
250 FIXME("(%p)->() stub!\n",This);
252 EnterCriticalSection( This->pcsReader );
253 LeaveCriticalSection( This->pcsReader );
258 static HRESULT WINAPI
259 CAsyncReaderImpl_fnSyncReadAligned(IAsyncReader* iface,IMediaSample* pSample)
261 ICOM_THIS(CAsyncReaderImpl,iface);
263 FIXME("(%p)->() stub!\n",This);
265 EnterCriticalSection( This->pcsReader );
266 LeaveCriticalSection( This->pcsReader );
271 static HRESULT WINAPI
272 CAsyncReaderImpl_fnSyncRead(IAsyncReader* iface,LONGLONG llPosStart,LONG lLength,BYTE* pbBuf)
274 ICOM_THIS(CAsyncReaderImpl,iface);
276 FIXME("(%p)->() stub!\n",This);
278 EnterCriticalSection( This->pcsReader );
279 LeaveCriticalSection( This->pcsReader );
284 static HRESULT WINAPI
285 CAsyncReaderImpl_fnLength(IAsyncReader* iface,LONGLONG* pllTotal,LONGLONG* pllAvailable)
287 ICOM_THIS(CAsyncReaderImpl,iface);
290 TRACE("(%p)->()\n",This);
292 EnterCriticalSection( This->pcsReader );
293 hr = This->pSource->m_pHandler->pGetLength( This->pSource, pllTotal, pllAvailable );
294 LeaveCriticalSection( This->pcsReader );
299 static HRESULT WINAPI
300 CAsyncReaderImpl_fnBeginFlush(IAsyncReader* iface)
302 ICOM_THIS(CAsyncReaderImpl,iface);
304 FIXME("(%p)->() stub!\n",This);
306 EnterCriticalSection( This->pcsReader );
307 LeaveCriticalSection( This->pcsReader );
312 static HRESULT WINAPI
313 CAsyncReaderImpl_fnEndFlush(IAsyncReader* iface)
315 ICOM_THIS(CAsyncReaderImpl,iface);
317 FIXME("(%p)->() stub!\n",This);
319 EnterCriticalSection( This->pcsReader );
320 LeaveCriticalSection( This->pcsReader );
326 static ICOM_VTABLE(IAsyncReader) iasyncreader =
328 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
329 /* IUnknown fields */
330 CAsyncReaderImpl_fnQueryInterface,
331 CAsyncReaderImpl_fnAddRef,
332 CAsyncReaderImpl_fnRelease,
334 /* IAsyncReader fields */
335 CAsyncReaderImpl_fnRequestAllocator,
336 CAsyncReaderImpl_fnRequest,
337 CAsyncReaderImpl_fnWaitForNext,
338 CAsyncReaderImpl_fnSyncReadAligned,
339 CAsyncReaderImpl_fnSyncRead,
340 CAsyncReaderImpl_fnLength,
341 CAsyncReaderImpl_fnBeginFlush,
342 CAsyncReaderImpl_fnEndFlush,
345 HRESULT CAsyncReaderImpl_InitIAsyncReader(
346 CAsyncReaderImpl* This, IUnknown* punkControl,
347 CAsyncSourceImpl* pSource,
348 CRITICAL_SECTION* pcsReader )
350 TRACE("(%p,%p)\n",This,punkControl);
352 if ( punkControl == NULL )
354 ERR( "punkControl must not be NULL\n" );
358 ICOM_VTBL(This) = &iasyncreader;
359 This->punkControl = punkControl;
360 This->pSource = pSource;
361 This->pcsReader = pcsReader;
362 This->m_hEventInit = (HANDLE)NULL;
363 This->m_hEventAbort = (HANDLE)NULL;
364 This->m_hEventReqQueued = (HANDLE)NULL;
365 This->m_hEventSampQueued = (HANDLE)NULL;
366 This->m_hEventCompletion = (HANDLE)NULL;
367 This->m_hThread = (HANDLE)NULL;
372 void CAsyncReaderImpl_UninitIAsyncReader(
373 CAsyncReaderImpl* This )
375 TRACE("(%p)\n",This);
378 /***************************************************************************
380 * CFileSourceFilterImpl
384 static HRESULT WINAPI
385 CFileSourceFilterImpl_fnQueryInterface(IFileSourceFilter* iface,REFIID riid,void** ppobj)
387 ICOM_THIS(CFileSourceFilterImpl,iface);
389 TRACE("(%p)->()\n",This);
391 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
395 CFileSourceFilterImpl_fnAddRef(IFileSourceFilter* iface)
397 ICOM_THIS(CFileSourceFilterImpl,iface);
399 TRACE("(%p)->()\n",This);
401 return IUnknown_AddRef(This->punkControl);
405 CFileSourceFilterImpl_fnRelease(IFileSourceFilter* iface)
407 ICOM_THIS(CFileSourceFilterImpl,iface);
409 TRACE("(%p)->()\n",This);
411 return IUnknown_Release(This->punkControl);
414 static HRESULT WINAPI
415 CFileSourceFilterImpl_fnLoad(IFileSourceFilter* iface,LPCOLESTR pFileName,const AM_MEDIA_TYPE* pmt)
417 ICOM_THIS(CFileSourceFilterImpl,iface);
420 TRACE("(%p)->(%s,%p)\n",This,debugstr_w(pFileName),pmt);
422 if ( pFileName == NULL )
425 if ( This->m_pwszFileName != NULL )
428 This->m_cbFileName = sizeof(WCHAR)*(lstrlenW(pFileName)+1);
429 This->m_pwszFileName = (WCHAR*)QUARTZ_AllocMem( This->m_cbFileName );
430 if ( This->m_pwszFileName == NULL )
431 return E_OUTOFMEMORY;
432 memcpy( This->m_pwszFileName, pFileName, This->m_cbFileName );
436 hr = QUARTZ_MediaType_Copy( &This->m_mt, pmt );
442 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
443 memcpy( &This->m_mt.majortype, &MEDIATYPE_Stream, sizeof(GUID) );
444 memcpy( &This->m_mt.subtype, &MEDIASUBTYPE_NULL, sizeof(GUID) );
445 This->m_mt.lSampleSize = 1;
446 memcpy( &This->m_mt.formattype, &FORMAT_None, sizeof(GUID) );
449 hr = This->pSource->m_pHandler->pLoad( This->pSource, pFileName );
458 static HRESULT WINAPI
459 CFileSourceFilterImpl_fnGetCurFile(IFileSourceFilter* iface,LPOLESTR* ppFileName,AM_MEDIA_TYPE* pmt)
461 ICOM_THIS(CFileSourceFilterImpl,iface);
462 HRESULT hr = E_NOTIMPL;
464 TRACE("(%p)->(%p,%p)\n",This,ppFileName,pmt);
466 if ( ppFileName == NULL || pmt == NULL )
469 if ( This->m_pwszFileName == NULL )
472 hr = QUARTZ_MediaType_Copy( pmt, &This->m_mt );
476 *ppFileName = (WCHAR*)CoTaskMemAlloc( This->m_cbFileName );
477 if ( *ppFileName == NULL )
479 QUARTZ_MediaType_Free(pmt);
480 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
481 return E_OUTOFMEMORY;
484 memcpy( *ppFileName, This->m_pwszFileName, This->m_cbFileName );
489 static ICOM_VTABLE(IFileSourceFilter) ifilesource =
491 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
492 /* IUnknown fields */
493 CFileSourceFilterImpl_fnQueryInterface,
494 CFileSourceFilterImpl_fnAddRef,
495 CFileSourceFilterImpl_fnRelease,
496 /* IFileSourceFilter fields */
497 CFileSourceFilterImpl_fnLoad,
498 CFileSourceFilterImpl_fnGetCurFile,
501 HRESULT CFileSourceFilterImpl_InitIFileSourceFilter(
502 CFileSourceFilterImpl* This, IUnknown* punkControl,
503 CAsyncSourceImpl* pSource,
504 CRITICAL_SECTION* pcsFileSource )
506 TRACE("(%p,%p)\n",This,punkControl);
508 if ( punkControl == NULL )
510 ERR( "punkControl must not be NULL\n" );
514 ICOM_VTBL(This) = &ifilesource;
515 This->punkControl = punkControl;
516 This->pSource = pSource;
517 This->pcsFileSource = pcsFileSource;
518 This->m_pwszFileName = NULL;
519 This->m_cbFileName = 0;
520 ZeroMemory( &This->m_mt, sizeof(AM_MEDIA_TYPE) );
525 void CFileSourceFilterImpl_UninitIFileSourceFilter(
526 CFileSourceFilterImpl* This )
528 TRACE("(%p)\n",This);
530 This->pSource->m_pHandler->pCleanup( This->pSource );
531 if ( This->m_pwszFileName != NULL )
532 QUARTZ_FreeMem( This->m_pwszFileName );
533 QUARTZ_MediaType_Free( &This->m_mt );
536 /***************************************************************************
538 * CAsyncSourcePinImpl methods
543 static HRESULT CAsyncSourcePinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
545 CAsyncSourcePinImpl_THIS(pImpl,pin);
547 This->bAsyncReaderQueried = FALSE;
552 static HRESULT CAsyncSourcePinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
554 CAsyncSourcePinImpl_THIS(pImpl,pin);
556 if ( !This->bAsyncReaderQueried )
562 static HRESULT CAsyncSourcePinImpl_OnDisconnect( CPinBaseImpl* pImpl )
564 CAsyncSourcePinImpl_THIS(pImpl,pin);
566 This->bAsyncReaderQueried = FALSE;
571 static HRESULT CAsyncSourcePinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
573 CAsyncSourcePinImpl_THIS(pImpl,pin);
575 TRACE("(%p,%p)\n",This,pmt);
579 if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
585 static const CBasePinHandlers outputpinhandlers =
587 CAsyncSourcePinImpl_OnPreConnect, /* pOnPreConnect */
588 CAsyncSourcePinImpl_OnPostConnect, /* pOnPostConnect */
589 CAsyncSourcePinImpl_OnDisconnect, /* pOnDisconnect */
590 CAsyncSourcePinImpl_CheckMediaType, /* pCheckMediaType */
591 NULL, /* pQualityNotify */
593 NULL, /* pReceiveCanBlock */
594 NULL, /* pEndOfStream */
595 NULL, /* pBeginFlush */
596 NULL, /* pEndFlush */
597 NULL, /* pNewSegment */
600 /***************************************************************************
602 * CAsyncSourceImpl methods
606 static HRESULT CAsyncSourceImpl_OnActive( CBaseFilterImpl* pImpl )
608 CAsyncSourceImpl_THIS(pImpl,basefilter);
611 TRACE( "(%p)\n", This );
613 hr = CAsyncReaderImpl_BeginThread(&This->pPin->async);
620 static HRESULT CAsyncSourceImpl_OnInactive( CBaseFilterImpl* pImpl )
622 CAsyncSourceImpl_THIS(pImpl,basefilter);
624 TRACE( "(%p)\n", This );
626 CAsyncReaderImpl_EndThread(&This->pPin->async);
631 static const CBaseFilterHandlers filterhandlers =
633 CAsyncSourceImpl_OnActive, /* pOnActive */
634 CAsyncSourceImpl_OnInactive, /* pOnInactive */
638 /***************************************************************************
640 * new/delete CAsyncSourceImpl
644 /* can I use offsetof safely? - FIXME? */
645 static QUARTZ_IFEntry FilterIFEntries[] =
647 { &IID_IPersist, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
648 { &IID_IMediaFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
649 { &IID_IBaseFilter, offsetof(CAsyncSourceImpl,basefilter)-offsetof(CAsyncSourceImpl,unk) },
650 { &IID_IFileSourceFilter, offsetof(CAsyncSourceImpl,filesrc)-offsetof(CAsyncSourceImpl,unk) },
653 static void QUARTZ_DestroyAsyncSource(IUnknown* punk)
655 CAsyncSourceImpl_THIS(punk,unk);
657 TRACE( "(%p)\n", This );
659 if ( This->pPin != NULL )
661 IUnknown_Release(This->pPin->unk.punkControl);
665 This->m_pHandler->pCleanup( This );
667 CFileSourceFilterImpl_UninitIFileSourceFilter(&This->filesrc);
668 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
670 DeleteCriticalSection( &This->csFilter );
673 HRESULT QUARTZ_CreateAsyncSource(
674 IUnknown* punkOuter,void** ppobj,
675 const CLSID* pclsidAsyncSource,
676 LPCWSTR pwszAsyncSourceName,
677 LPCWSTR pwszOutPinName,
678 const AsyncSourceHandlers* pHandler )
680 CAsyncSourceImpl* This = NULL;
683 TRACE("(%p,%p)\n",punkOuter,ppobj);
685 This = (CAsyncSourceImpl*)
686 QUARTZ_AllocObj( sizeof(CAsyncSourceImpl) );
688 return E_OUTOFMEMORY;
691 This->m_pHandler = pHandler;
692 This->m_pUserData = NULL;
694 QUARTZ_IUnkInit( &This->unk, punkOuter );
696 hr = CBaseFilterImpl_InitIBaseFilter(
698 This->unk.punkControl,
704 /* construct this class. */
705 hr = CFileSourceFilterImpl_InitIFileSourceFilter(
706 &This->filesrc, This->unk.punkControl,
707 This, &This->csFilter );
710 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
716 QUARTZ_FreeObj(This);
720 This->unk.pEntries = FilterIFEntries;
721 This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]);
722 This->unk.pOnFinalRelease = QUARTZ_DestroyAsyncSource;
723 InitializeCriticalSection( &This->csFilter );
725 /* create the output pin. */
730 IUnknown_Release( This->unk.punkControl );
734 *ppobj = (void*)&(This->unk);
739 /***************************************************************************
741 * new/delete CAsyncSourcePinImpl
745 /* can I use offsetof safely? - FIXME? */
746 static QUARTZ_IFEntry OutPinIFEntries[] =
748 { &IID_IPin, offsetof(CAsyncSourcePinImpl,pin)-offsetof(CAsyncSourcePinImpl,unk) },
749 /***{ &IID_IAsyncReader, offsetof(CAsyncSourcePinImpl,async)-offsetof(CAsyncSourcePinImpl,unk) },***/
752 static HRESULT CAsyncSourceImpl_OnQueryInterface(
753 IUnknown* punk, const IID* piid, void** ppobj )
755 CAsyncSourcePinImpl_THIS(punk,unk);
757 if ( IsEqualGUID( &IID_IAsyncReader, piid ) )
759 *ppobj = (void*)&This->async;
760 IUnknown_AddRef(punk);
761 This->bAsyncReaderQueried = TRUE;
765 return E_NOINTERFACE;
768 static void QUARTZ_DestroyAsyncSourcePin(IUnknown* punk)
770 CAsyncSourcePinImpl_THIS(punk,unk);
772 TRACE( "(%p)\n", This );
774 CAsyncReaderImpl_UninitIAsyncReader( &This->async );
775 CPinBaseImpl_UninitIPin( &This->pin );
778 HRESULT QUARTZ_CreateAsyncSourcePin(
779 CAsyncSourceImpl* pFilter,
780 CRITICAL_SECTION* pcsPin,
781 CAsyncSourcePinImpl** ppPin,
782 LPCWSTR pwszPinName )
784 CAsyncSourcePinImpl* This = NULL;
787 TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
789 This = (CAsyncSourcePinImpl*)
790 QUARTZ_AllocObj( sizeof(CAsyncSourcePinImpl) );
792 return E_OUTOFMEMORY;
794 QUARTZ_IUnkInit( &This->unk, NULL );
795 This->qiext.pNext = NULL;
796 This->qiext.pOnQueryInterface = &CAsyncSourceImpl_OnQueryInterface;
797 QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
799 This->bAsyncReaderQueried = FALSE;
800 This->pSource = pFilter;
802 hr = CPinBaseImpl_InitIPin(
804 This->unk.punkControl,
806 &pFilter->basefilter,
809 &outputpinhandlers );
813 hr = CAsyncReaderImpl_InitIAsyncReader(
815 This->unk.punkControl,
820 CPinBaseImpl_UninitIPin( &This->pin );
826 QUARTZ_FreeObj(This);
830 This->unk.pEntries = OutPinIFEntries;
831 This->unk.dwEntries = sizeof(OutPinIFEntries)/sizeof(OutPinIFEntries[0]);
832 This->unk.pOnFinalRelease = QUARTZ_DestroyAsyncSourcePin;
836 TRACE("returned successfully.\n");