Fixed some bugs.
[wine/multimedia.git] / dlls / quartz / asyncsrc.c
blob6fd644d533fb9daf70ed9de00a56ca76b8f074e2
1 /*
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
23 #include "config.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
30 #include "strmif.h"
31 #include "vfwmsgs.h"
32 #include "uuids.h"
34 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
37 #include "quartz_private.h"
38 #include "asyncsrc.h"
39 #include "memalloc.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[] =
46 {'O','u','t',0};
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[] =
50 {'O','u','t',0};
54 /***************************************************************************
56 * CAsyncReaderImpl internal methods
60 static
61 AsyncSourceRequest* CAsyncReaderImpl_AllocRequest( CAsyncReaderImpl* This )
63 AsyncSourceRequest* pReq;
65 EnterCriticalSection( &This->m_csFree );
66 pReq = This->m_pFreeFirst;
67 if ( pReq != NULL )
68 This->m_pFreeFirst = pReq->pNext;
69 LeaveCriticalSection( &This->m_csFree );
71 if ( pReq == NULL )
73 pReq = (AsyncSourceRequest*)QUARTZ_AllocMem(
74 sizeof(AsyncSourceRequest) );
75 if ( pReq == NULL )
76 return NULL;
79 pReq->pNext = NULL;
80 pReq->llStart = 0;
81 pReq->lLength = 0;
82 pReq->lActual = 0;
83 pReq->pBuf = NULL;
84 pReq->pSample = NULL;
85 pReq->dwContext = 0;
87 return pReq;
90 static
91 void CAsyncReaderImpl_FreeRequest( CAsyncReaderImpl* This, AsyncSourceRequest* pReq, BOOL bReleaseMem )
93 if ( !bReleaseMem )
95 EnterCriticalSection( &This->m_csFree );
96 pReq->pNext = This->m_pFreeFirst;
97 This->m_pFreeFirst = pReq;
98 LeaveCriticalSection( &This->m_csFree );
100 else
102 QUARTZ_FreeMem( pReq );
106 static
107 AsyncSourceRequest* CAsyncReaderImpl_GetRequest( CAsyncReaderImpl* This )
109 AsyncSourceRequest* pReq;
111 EnterCriticalSection( &This->m_csRequest );
112 pReq = This->m_pRequestFirst;
113 if ( pReq != NULL )
114 This->m_pRequestFirst = pReq->pNext;
115 LeaveCriticalSection( &This->m_csRequest );
117 return pReq;
120 static
121 AsyncSourceRequest* CAsyncReaderImpl_GetReply( CAsyncReaderImpl* This )
123 AsyncSourceRequest* pReq;
125 EnterCriticalSection( &This->m_csReply );
126 pReq = This->m_pReplyFirst;
127 if ( pReq != NULL )
128 This->m_pReplyFirst = pReq->pNext;
129 LeaveCriticalSection( &This->m_csReply );
131 return pReq;
134 static
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 );
146 static
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 );
158 static
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);
170 pReq = pReqNext;
174 static DWORD WINAPI
175 CAsyncReaderImpl_ThreadEntry( LPVOID pv )
177 CAsyncReaderImpl* This = (CAsyncReaderImpl*)pv;
178 HANDLE hWaitEvents[2];
179 HRESULT hr;
180 DWORD dwRes;
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");
190 while ( 1 )
192 ResetEvent( This->m_hEventReqQueued );
193 pReq = CAsyncReaderImpl_GetRequest(This);
194 if ( pReq == NULL )
196 dwRes = WaitForMultipleObjects(2,hWaitEvents,FALSE,INFINITE);
197 if ( dwRes != WAIT_OBJECT_0 )
199 if ( This->m_bAbortThread )
200 break;
202 continue;
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 );
210 if ( FAILED(hr) )
212 /* Notify(ABORT) */
213 break;
215 if ( hr != S_OK )
217 if ( This->m_bAbortThread )
218 break;
219 ResetEvent( This->m_hEventCancel );
222 CAsyncReaderImpl_PostReply( This, pReq );
223 SetEvent( This->m_hEventSampQueued );
224 pReq = NULL;
227 if ( pReq != NULL )
228 CAsyncReaderImpl_PostRequest( This, pReq );
230 SetEvent( This->m_hEventSampQueued );
231 return 0;
234 static HRESULT
235 CAsyncReaderImpl_BeginThread( CAsyncReaderImpl* This )
237 DWORD dwRes;
238 DWORD dwThreadId;
239 HANDLE hEvents[2];
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 )
246 return E_UNEXPECTED;
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(
264 NULL, 0,
265 CAsyncReaderImpl_ThreadEntry,
266 (LPVOID)This,
267 0, &dwThreadId );
268 if ( This->m_hThread == (HANDLE)NULL )
269 return E_FAIL;
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 )
276 return E_FAIL;
278 return NOERROR;
281 static void
282 CAsyncReaderImpl_EndThread( CAsyncReaderImpl* This )
284 if ( This->m_hThread != (HANDLE)NULL )
286 while ( 1 )
288 This->m_bAbortThread = TRUE;
289 SetEvent( This->m_hEventCancel );
290 if ( WaitForSingleObject( This->m_hThread, 100 ) == WAIT_OBJECT_0 )
291 break;
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);
334 static ULONG WINAPI
335 CAsyncReaderImpl_fnAddRef(IAsyncReader* iface)
337 ICOM_THIS(CAsyncReaderImpl,iface);
339 TRACE("(%p)->()\n",This);
341 return IUnknown_AddRef(This->punkControl);
344 static ULONG WINAPI
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);
358 HRESULT hr;
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 )
365 return E_POINTER;
367 IMemAllocator_AddRef(pAlloc);
368 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
369 if ( SUCCEEDED(hr) )
371 *ppAllocActual = pAlloc;
372 return S_OK;
374 IMemAllocator_Release(pAlloc);
376 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
377 if ( FAILED(hr) )
378 return hr;
379 hr = IUnknown_QueryInterface( punk, &IID_IMemAllocator, (void**)&pAlloc );
380 IUnknown_Release(punk);
381 if ( FAILED(hr) )
382 return hr;
384 hr = IMemAllocator_SetProperties( pAlloc, pProp, &propActual );
385 if ( SUCCEEDED(hr) )
387 *ppAllocActual = pAlloc;
388 return S_OK;
390 IMemAllocator_Release(pAlloc);
392 return hr;
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;
403 BYTE* pData = NULL;
405 TRACE("(%p)->(%p,%u)\n",This,pSample,dwContext);
407 hr = IMediaSample_GetPointer(pSample,&pData);
408 if ( SUCCEEDED(hr) )
409 hr = IMediaSample_GetTime(pSample,&rtStart,&rtEnd);
410 if ( FAILED(hr) )
411 return hr;
413 pReq = CAsyncReaderImpl_AllocRequest(This);
414 if ( pReq == NULL )
415 return E_OUTOFMEMORY;
417 pReq->llStart = rtStart / QUARTZ_TIMEUNITS;
418 pReq->lLength = (LONG)(rtEnd / QUARTZ_TIMEUNITS - rtStart / QUARTZ_TIMEUNITS);
419 pReq->lActual = 0;
420 pReq->pBuf = pData;
421 pReq->pSample = pSample;
422 pReq->dwContext = dwContext;
423 CAsyncReaderImpl_PostRequest( This, pReq );
425 return NOERROR;
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;
433 DWORD dwRes;
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 )
442 hr = VFW_E_TIMEOUT;
443 LeaveCriticalSection( &This->m_csRequest );
445 if ( hr == NOERROR )
447 ResetEvent( This->m_hEventSampQueued );
448 pReq = CAsyncReaderImpl_GetReply(This);
449 if ( pReq == NULL )
451 dwRes = WaitForSingleObject( This->m_hEventSampQueued, dwTimeout );
452 if ( dwRes == WAIT_OBJECT_0 )
453 pReq = CAsyncReaderImpl_GetReply(This);
455 if ( pReq != NULL )
457 hr = IMediaSample_SetActualDataLength(pReq->pSample,pReq->lActual);
458 if ( hr == S_OK )
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 )
467 hr = S_FALSE;
469 else
471 hr = VFW_E_TIMEOUT;
475 return hr;
478 static HRESULT WINAPI
479 CAsyncReaderImpl_fnSyncReadAligned(IAsyncReader* iface,IMediaSample* pSample)
481 ICOM_THIS(CAsyncReaderImpl,iface);
482 HRESULT hr;
483 REFERENCE_TIME rtStart;
484 REFERENCE_TIME rtEnd;
485 BYTE* pData = NULL;
486 LONGLONG llStart;
487 LONG lLength;
488 LONG lActual;
490 TRACE("(%p)->(%p)\n",This,pSample);
492 hr = IMediaSample_GetPointer(pSample,&pData);
493 if ( SUCCEEDED(hr) )
494 hr = IMediaSample_GetTime(pSample,&rtStart,&rtEnd);
495 if ( FAILED(hr) )
496 return hr;
498 llStart = rtStart / QUARTZ_TIMEUNITS;
499 lLength = (LONG)(rtEnd / QUARTZ_TIMEUNITS - rtStart / QUARTZ_TIMEUNITS);
500 lActual = 0;
501 if ( lLength > IMediaSample_GetSize(pSample) )
503 FIXME("invalid length\n");
504 return E_FAIL;
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 );
511 if ( hr == NOERROR )
513 hr = IMediaSample_SetActualDataLength(pSample,lActual);
514 if ( hr == S_OK )
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 )
521 hr = S_FALSE;
524 return hr;
527 static HRESULT WINAPI
528 CAsyncReaderImpl_fnSyncRead(IAsyncReader* iface,LONGLONG llPosStart,LONG lLength,BYTE* pbBuf)
530 ICOM_THIS(CAsyncReaderImpl,iface);
531 HRESULT hr;
532 LONG lActual;
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 )
541 hr = S_FALSE;
543 return hr;
546 static HRESULT WINAPI
547 CAsyncReaderImpl_fnLength(IAsyncReader* iface,LONGLONG* pllTotal,LONGLONG* pllAvailable)
549 ICOM_THIS(CAsyncReaderImpl,iface);
550 HRESULT hr;
552 TRACE("(%p)->()\n",This);
554 hr = This->pSource->m_pHandler->pGetLength( This->pSource, pllTotal, pllAvailable );
556 return hr;
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 );
572 return NOERROR;
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 );
587 return NOERROR;
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" );
619 return E_INVALIDARG;
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 );
641 return NOERROR;
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);
677 static ULONG WINAPI
678 CFileSourceFilterImpl_fnAddRef(IFileSourceFilter* iface)
680 ICOM_THIS(CFileSourceFilterImpl,iface);
682 TRACE("(%p)->()\n",This);
684 return IUnknown_AddRef(This->punkControl);
687 static ULONG WINAPI
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);
701 HRESULT hr;
703 TRACE("(%p)->(%s,%p)\n",This,debugstr_w(pFileName),pmt);
705 if ( pFileName == NULL )
706 return E_POINTER;
708 if ( This->m_pwszFileName != NULL )
709 return E_UNEXPECTED;
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 );
717 if ( pmt != NULL )
719 hr = QUARTZ_MediaType_Copy( &This->m_mt, pmt );
720 if ( FAILED(hr) )
721 goto err;
723 else
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 );
733 if ( FAILED(hr) )
734 goto err;
736 This->pSource->pPin->pin.pmtAcceptTypes = &This->m_mt;
737 This->pSource->pPin->pin.cAcceptTypes = 1;
739 return NOERROR;
740 err:;
741 return hr;
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 )
753 return E_POINTER;
755 if ( This->m_pwszFileName == NULL )
756 return E_FAIL;
758 hr = QUARTZ_MediaType_Copy( pmt, &This->m_mt );
759 if ( FAILED(hr) )
760 return hr;
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 );
772 return NOERROR;
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" );
797 return E_INVALIDARG;
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) );
808 return NOERROR;
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;
837 return NOERROR;
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 )
847 return E_FAIL;
849 return NOERROR;
852 static HRESULT CAsyncSourcePinImpl_OnDisconnect( CPinBaseImpl* pImpl )
854 CAsyncSourcePinImpl_THIS(pImpl,pin);
856 TRACE("(%p)\n",This);
858 This->bAsyncReaderQueried = FALSE;
860 return NOERROR;
863 static HRESULT CAsyncSourcePinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
865 CAsyncSourcePinImpl_THIS(pImpl,pin);
867 TRACE("(%p,%p)\n",This,pmt);
868 if ( pmt == NULL )
869 return E_POINTER;
871 if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
872 return E_FAIL;
874 return NOERROR;
877 static const CBasePinHandlers outputpinhandlers =
879 CAsyncSourcePinImpl_OnPreConnect, /* pOnPreConnect */
880 CAsyncSourcePinImpl_OnPostConnect, /* pOnPostConnect */
881 CAsyncSourcePinImpl_OnDisconnect, /* pOnDisconnect */
882 CAsyncSourcePinImpl_CheckMediaType, /* pCheckMediaType */
883 NULL, /* pQualityNotify */
884 NULL, /* pReceive */
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);
901 HRESULT hr;
903 TRACE( "(%p)\n", This );
905 hr = CAsyncReaderImpl_BeginThread(&This->pPin->async);
906 if ( FAILED(hr) )
907 return hr;
909 return NOERROR;
912 static HRESULT CAsyncSourceImpl_OnInactive( CBaseFilterImpl* pImpl )
914 CAsyncSourceImpl_THIS(pImpl,basefilter);
916 TRACE( "(%p)\n", This );
918 CAsyncReaderImpl_EndThread(&This->pPin->async);
920 return NOERROR;
923 static const CBaseFilterHandlers filterhandlers =
925 CAsyncSourceImpl_OnActive, /* pOnActive */
926 CAsyncSourceImpl_OnInactive, /* pOnInactive */
927 NULL, /* pOnStop */
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);
954 This->pPin = NULL;
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;
973 HRESULT hr;
975 TRACE("(%p,%p)\n",punkOuter,ppobj);
977 This = (CAsyncSourceImpl*)
978 QUARTZ_AllocObj( sizeof(CAsyncSourceImpl) );
979 if ( This == NULL )
980 return E_OUTOFMEMORY;
982 This->pPin = NULL;
983 This->m_pHandler = pHandler;
984 This->m_pUserData = NULL;
986 QUARTZ_IUnkInit( &This->unk, punkOuter );
988 hr = CBaseFilterImpl_InitIBaseFilter(
989 &This->basefilter,
990 This->unk.punkControl,
991 pclsidAsyncSource,
992 pwszAsyncSourceName,
993 &filterhandlers );
994 if ( SUCCEEDED(hr) )
996 /* construct this class. */
997 hr = CFileSourceFilterImpl_InitIFileSourceFilter(
998 &This->filesrc, This->unk.punkControl,
999 This, &This->csFilter );
1000 if ( FAILED(hr) )
1002 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
1006 if ( FAILED(hr) )
1008 QUARTZ_FreeObj(This);
1009 return hr;
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),
1025 NULL, 0 );
1027 if ( FAILED(hr) )
1029 IUnknown_Release( This->unk.punkControl );
1030 return hr;
1033 *ppobj = (void*)&(This->unk);
1035 return S_OK;
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;
1062 return S_OK;
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;
1085 HRESULT hr;
1087 TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
1089 This = (CAsyncSourcePinImpl*)
1090 QUARTZ_AllocObj( sizeof(CAsyncSourcePinImpl) );
1091 if ( This == NULL )
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(
1103 &This->pin,
1104 This->unk.punkControl,
1105 pcsPin, NULL,
1106 &pFilter->basefilter,
1107 pwszPinName,
1108 TRUE,
1109 &outputpinhandlers );
1111 if ( SUCCEEDED(hr) )
1113 hr = CAsyncReaderImpl_InitIAsyncReader(
1114 &This->async,
1115 This->unk.punkControl,
1116 pFilter );
1117 if ( FAILED(hr) )
1119 CPinBaseImpl_UninitIPin( &This->pin );
1123 if ( FAILED(hr) )
1125 QUARTZ_FreeObj(This);
1126 return hr;
1129 This->unk.pEntries = OutPinIFEntries;
1130 This->unk.dwEntries = sizeof(OutPinIFEntries)/sizeof(OutPinIFEntries[0]);
1131 This->unk.pOnFinalRelease = QUARTZ_DestroyAsyncSourcePin;
1133 *ppPin = This;
1135 TRACE("returned successfully.\n");
1137 return S_OK;
1142 /***************************************************************************
1144 * Implements File Source.
1148 typedef struct AsyncSourceFileImpl
1150 HANDLE hFile;
1151 LONGLONG llTotal;
1152 } AsyncSourceFileImpl;
1155 static HRESULT AsyncSourceFileImpl_Load( CAsyncSourceImpl* pImpl, LPCWSTR lpwszSourceName )
1157 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1158 DWORD dwLow;
1159 DWORD dwHigh;
1161 if ( This != NULL )
1162 return E_UNEXPECTED;
1163 This = (AsyncSourceFileImpl*)QUARTZ_AllocMem( sizeof(AsyncSourceFileImpl) );
1164 pImpl->m_pUserData = (void*)This;
1165 if ( This == NULL )
1166 return E_OUTOFMEMORY;
1167 This->hFile = INVALID_HANDLE_VALUE;
1168 This->llTotal = 0;
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 )
1174 return E_FAIL;
1176 SetLastError(NO_ERROR);
1177 dwLow = GetFileSize( This->hFile, &dwHigh );
1178 if ( dwLow == 0xffffffff && GetLastError() != NO_ERROR )
1179 return E_FAIL;
1181 This->llTotal = (LONGLONG)dwLow | ((LONGLONG)dwHigh << 32);
1183 return NOERROR;
1186 static HRESULT AsyncSourceFileImpl_Cleanup( CAsyncSourceImpl* pImpl )
1188 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1190 if ( This == NULL )
1191 return NOERROR;
1193 if ( This->hFile != INVALID_HANDLE_VALUE )
1194 CloseHandle(This->hFile);
1196 QUARTZ_FreeMem(This);
1197 pImpl->m_pUserData = NULL;
1199 return NOERROR;
1202 static HRESULT AsyncSourceFileImpl_GetLength( CAsyncSourceImpl* pImpl, LONGLONG* pllTotal, LONGLONG* pllAvailable )
1204 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1206 if ( This == NULL )
1207 return E_UNEXPECTED;
1209 *pllTotal = This->llTotal;
1210 *pllAvailable = This->llTotal;
1212 return NOERROR;
1215 static HRESULT AsyncSourceFileImpl_Read( CAsyncSourceImpl* pImpl, LONGLONG llOfsStart, LONG lLength, BYTE* pBuf, LONG* plReturned, HANDLE hEventCancel )
1217 AsyncSourceFileImpl* This = (AsyncSourceFileImpl*)pImpl->m_pUserData;
1218 LONG lReturned;
1219 LONG lBlock;
1220 LONG lOfsLow;
1221 LONG lOfsHigh;
1222 DWORD dw;
1223 HRESULT hr = S_OK;
1225 if ( This == NULL || This->hFile == INVALID_HANDLE_VALUE )
1226 return E_UNEXPECTED;
1228 lReturned = 0;
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 )
1235 return E_FAIL;
1237 while ( lLength > 0 )
1239 if ( hEventCancel != (HANDLE)NULL &&
1240 WaitForSingleObject( hEventCancel, 0 ) == WAIT_OBJECT_0 )
1242 hr = S_FALSE;
1243 break;
1246 lBlock = ( lLength > ASYNCSRC_FILE_BLOCKSIZE ) ?
1247 ASYNCSRC_FILE_BLOCKSIZE : lLength;
1249 if ( !ReadFile(This->hFile,pBuf,(DWORD)lBlock,&dw,NULL) )
1251 hr = E_FAIL;
1252 break;
1254 pBuf += dw;
1255 lReturned += (LONG)dw;
1256 lLength -= (LONG)dw;
1257 if ( lBlock > (LONG)dw )
1258 break;
1261 *plReturned = lReturned;
1263 return hr;
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(
1277 punkOuter, ppobj,
1278 &CLSID_AsyncReader,
1279 QUARTZ_wszAsyncFileSourceName,
1280 QUARTZ_wszAsyncFileSourcePinName,
1281 &asyncsrc_file );
1284 /***************************************************************************
1286 * Implements URL Source.
1290 typedef struct AsyncSourceURLImpl
1292 DWORD dwDummy;
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);
1302 if ( This != NULL )
1303 return E_UNEXPECTED;
1304 This = (AsyncSourceURLImpl*)QUARTZ_AllocMem( sizeof(AsyncSourceURLImpl) );
1305 pImpl->m_pUserData = (void*)This;
1306 if ( This == NULL )
1307 return E_OUTOFMEMORY;
1309 return E_NOTIMPL;
1312 static HRESULT AsyncSourceURLImpl_Cleanup( CAsyncSourceImpl* pImpl )
1314 AsyncSourceURLImpl* This = (AsyncSourceURLImpl*)pImpl->m_pUserData;
1316 FIXME("(%p) stub!\n", This);
1318 if ( This == NULL )
1319 return NOERROR;
1321 QUARTZ_FreeMem(This);
1322 pImpl->m_pUserData = NULL;
1324 return NOERROR;
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);
1333 if ( This == NULL )
1334 return E_UNEXPECTED;
1336 return E_NOTIMPL;
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);
1345 if ( This == NULL )
1346 return E_UNEXPECTED;
1348 return E_NOTIMPL;
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(
1363 punkOuter, ppobj,
1364 &CLSID_URLReader,
1365 QUARTZ_wszAsyncURLSourceName,
1366 QUARTZ_wszAsyncURLSourcePinName,
1367 &asyncsrc_url );