diff --git a/dlls/quartz/Makefile.in b/dlls/quartz/Makefile.in index 64fb6df938..dd9a5d429a 100644 --- a/dlls/quartz/Makefile.in +++ b/dlls/quartz/Makefile.in @@ -10,6 +10,7 @@ SYMBOLFILE = $(MODULE).tmp.o C_SRCS = \ amundoc.c \ + audren.c \ basefilt.c \ basepin.c \ complist.c \ diff --git a/dlls/quartz/audren.c b/dlls/quartz/audren.c new file mode 100644 index 0000000000..0a1810377a --- /dev/null +++ b/dlls/quartz/audren.c @@ -0,0 +1,841 @@ +/* + * Audio Renderer (CLSID_AudioRender) + * + * FIXME + * - implements IRefereneceClock. + * - implements seeking. + * + * hidenori@a2.ctktv.ne.jp + */ + +#include "config.h" + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "mmsystem.h" +#include "winerror.h" +#include "wine/obj_base.h" +#include "wine/obj_oleaut.h" +#include "strmif.h" +#include "control.h" +#include "vfwmsgs.h" +#include "uuids.h" + +#include "debugtools.h" +DEFAULT_DEBUG_CHANNEL(quartz); + +#include "quartz_private.h" +#include "audren.h" + + +static const WCHAR QUARTZ_AudioRender_Name[] = +{ 'A','u','d','i','o',' ','R','e','n','d','e','r',0 }; +static const WCHAR QUARTZ_AudioRenderPin_Name[] = +{ 'I','n',0 }; + + + +/*************************************************************************** + * + * CAudioRendererImpl waveOut methods (internal) + * + */ + +static +HRESULT QUARTZ_HRESULT_From_MMRESULT( MMRESULT mr ) +{ + HRESULT hr = E_FAIL; + + switch ( mr ) + { + case MMSYSERR_NOERROR: + hr = S_OK; + break; + case MMSYSERR_NOMEM: + hr = E_OUTOFMEMORY; + break; + } + + return hr; +} + +void CAudioRendererImpl_waveOutEventCallback( + HWAVEOUT hwo, UINT uMsg, + DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ) +{ + CAudioRendererImpl* This = (CAudioRendererImpl*)dwInstance; + + if ( uMsg == WOM_DONE ) + SetEvent( This->m_hEventRender ); +} + +static +void CAudioRendererImpl_waveOutReset( + CAudioRendererImpl* This ) +{ + if ( !This->m_fWaveOutInit ) + return; + + waveOutReset( This->m_hWaveOut ); + SetEvent( This->m_hEventRender ); +} + +static +void CAudioRendererImpl_waveOutUninit( + CAudioRendererImpl* This ) +{ + DWORD i; + + TRACE("(%p)\n",This); + + if ( !This->m_fWaveOutInit ) + return; + + waveOutReset( This->m_hWaveOut ); + SetEvent( This->m_hEventRender ); + + for ( i = 0; i < WINE_QUARTZ_WAVEOUT_COUNT; i++ ) + { + if ( This->m_hdr[i].dwFlags & WHDR_PREPARED ) + { + waveOutUnprepareHeader( + This->m_hWaveOut, + &This->m_hdr[i], sizeof(WAVEHDR) ); + This->m_hdr[i].dwFlags = 0; + } + if ( This->m_hdr[i].lpData != NULL ) + { + QUARTZ_FreeMem( This->m_hdr[i].lpData ); + This->m_hdr[i].lpData = NULL; + } + } + + waveOutClose( This->m_hWaveOut ); + This->m_hWaveOut = (HWAVEOUT)NULL; + if ( This->m_hEventRender != (HANDLE)NULL ) + { + CloseHandle( This->m_hEventRender ); + This->m_hEventRender = (HANDLE)NULL; + } + + This->m_fWaveOutInit = FALSE; +} + +static +HRESULT CAudioRendererImpl_waveOutInit( + CAudioRendererImpl* This, WAVEFORMATEX* pwfx ) +{ + MMRESULT mr; + HRESULT hr; + DWORD i; + DWORD dwBlockSize; + + if ( This->m_fWaveOutInit ) + return E_UNEXPECTED; + + if ( pwfx == NULL ) + return E_POINTER; + if ( pwfx->nBlockAlign == 0 ) + return E_INVALIDARG; + + This->m_hEventRender = (HANDLE)NULL; + This->m_hWaveOut = (HWAVEOUT)NULL; + This->m_dwBlockSize = 0; + This->m_phdrCur = NULL; + ZeroMemory( &This->m_hdr, sizeof(This->m_hdr) ); + + + mr = waveOutOpen( + &This->m_hWaveOut, WAVE_MAPPER, pwfx, + (DWORD)CAudioRendererImpl_waveOutEventCallback, (DWORD)This, + CALLBACK_FUNCTION ); + hr = QUARTZ_HRESULT_From_MMRESULT( mr ); + if ( FAILED(hr) ) + return hr; + This->m_fWaveOutInit = TRUE; + + This->m_hEventRender = CreateEventA( + NULL, TRUE, TRUE, NULL ); + if ( This->m_hEventRender == (HANDLE)NULL ) + { + hr = E_OUTOFMEMORY; + goto err; + } + + dwBlockSize = pwfx->nAvgBytesPerSec / pwfx->nBlockAlign; + if ( dwBlockSize == 0 ) + dwBlockSize = 1; + dwBlockSize *= pwfx->nBlockAlign; + This->m_dwBlockSize = dwBlockSize; + + for ( i = 0; i < WINE_QUARTZ_WAVEOUT_COUNT; i++ ) + { + This->m_hdr[i].lpData = (CHAR*)QUARTZ_AllocMem( dwBlockSize ); + if ( This->m_hdr[i].lpData == NULL ) + { + hr = E_OUTOFMEMORY; + goto err; + } + mr = waveOutPrepareHeader( + This->m_hWaveOut, + &This->m_hdr[i], sizeof(WAVEHDR) ); + hr = QUARTZ_HRESULT_From_MMRESULT( mr ); + if ( FAILED(hr) ) + goto err; + This->m_hdr[i].dwFlags |= WHDR_DONE; + This->m_hdr[i].dwBufferLength = dwBlockSize; + This->m_hdr[i].dwUser = i; + } + + return S_OK; +err: + CAudioRendererImpl_waveOutUninit(This); + return hr; +} + +static +WAVEHDR* CAudioRendererImpl_waveOutGetBuffer( + CAudioRendererImpl* This ) +{ + DWORD i; + + if ( !This->m_fWaveOutInit ) + return NULL; + + if ( This->m_phdrCur != NULL ) + return This->m_phdrCur; + + for ( i = 0; i < WINE_QUARTZ_WAVEOUT_COUNT; i++ ) + { + if ( This->m_hdr[i].dwFlags & WHDR_DONE ) + { + This->m_phdrCur = &(This->m_hdr[i]); + This->m_phdrCur->dwFlags &= ~WHDR_DONE; + This->m_phdrCur->dwBufferLength = 0; + return This->m_phdrCur; + } + } + + return NULL; +} + +static +HRESULT CAudioRendererImpl_waveOutWriteData( + CAudioRendererImpl* This, + const BYTE* pData, DWORD cbData, DWORD* pcbWritten ) +{ + DWORD cbAvail; + + *pcbWritten = 0; + + if ( !This->m_fWaveOutInit ) + return E_UNEXPECTED; + + if ( cbData == 0 ) + return S_OK; + + if ( CAudioRendererImpl_waveOutGetBuffer(This) == NULL ) + return S_FALSE; + + cbAvail = This->m_dwBlockSize - This->m_phdrCur->dwBufferLength; + if ( cbAvail > cbData ) + cbAvail = cbData; + memcpy( This->m_phdrCur->lpData, pData, cbAvail ); + pData += cbAvail; + cbData -= cbAvail; + This->m_phdrCur->dwBufferLength += cbAvail; + + *pcbWritten = cbAvail; + + return S_OK; +} + +static +HRESULT CAudioRendererImpl_waveOutFlush( + CAudioRendererImpl* This ) +{ + MMRESULT mr; + HRESULT hr; + + if ( !This->m_fWaveOutInit ) + return E_UNEXPECTED; + if ( This->m_phdrCur == NULL ) + return E_UNEXPECTED; + + if ( This->m_phdrCur->dwBufferLength == 0 ) + return S_OK; + + mr = waveOutWrite( + This->m_hWaveOut, + This->m_phdrCur, sizeof(WAVEHDR) ); + hr = QUARTZ_HRESULT_From_MMRESULT( mr ); + if ( FAILED(hr) ) + return hr; + + This->m_phdrCur = NULL; + return S_OK; +} + +static +HRESULT CAudioRendererImpl_waveOutGetVolume( + CAudioRendererImpl* This, + DWORD* pdwLeft, DWORD* pdwRight ) +{ + MMRESULT mr; + HRESULT hr; + DWORD dwVol; + + if ( !This->m_fWaveOutInit ) + return E_UNEXPECTED; + + mr = waveOutGetVolume( + This->m_hWaveOut, &dwVol ); + hr = QUARTZ_HRESULT_From_MMRESULT( mr ); + if ( FAILED(hr) ) + return hr; + + *pdwLeft = LOWORD(dwVol); + *pdwRight = HIWORD(dwVol); + + return NOERROR; +} + +static +HRESULT CAudioRendererImpl_waveOutSetVolume( + CAudioRendererImpl* This, + DWORD dwLeft, DWORD dwRight ) +{ + MMRESULT mr; + DWORD dwVol; + + if ( !This->m_fWaveOutInit ) + return E_UNEXPECTED; + + dwVol = dwLeft | (dwRight<<16); + + mr = waveOutSetVolume( + This->m_hWaveOut, dwVol ); + return QUARTZ_HRESULT_From_MMRESULT( mr ); +} + +/*************************************************************************** + * + * CAudioRendererImpl methods + * + */ + + +static HRESULT CAudioRendererImpl_OnActive( CBaseFilterImpl* pImpl ) +{ + CAudioRendererImpl_THIS(pImpl,basefilter); + WAVEFORMATEX* pwfx; + + FIXME( "(%p)\n", This ); + + if ( This->pPin->pin.pmtConn == NULL ) + return NOERROR; + + pwfx = (WAVEFORMATEX*)This->pPin->pin.pmtConn->pbFormat; + if ( pwfx == NULL ) + return E_FAIL; + + This->m_fInFlush = FALSE; + + return CAudioRendererImpl_waveOutInit(This,pwfx); +} + +static HRESULT CAudioRendererImpl_OnInactive( CBaseFilterImpl* pImpl ) +{ + CAudioRendererImpl_THIS(pImpl,basefilter); + + FIXME( "(%p)\n", This ); + + CAudioRendererImpl_waveOutUninit(This); + + This->m_fInFlush = FALSE; + + TRACE("returned\n" ); + + return NOERROR; +} + +static const CBaseFilterHandlers filterhandlers = +{ + CAudioRendererImpl_OnActive, /* pOnActive */ + CAudioRendererImpl_OnInactive, /* pOnInactive */ +}; + +/*************************************************************************** + * + * CAudioRendererPinImpl methods + * + */ + +static HRESULT CAudioRendererPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt ) +{ + CAudioRendererPinImpl_THIS(pImpl,pin); + const WAVEFORMATEX* pwfx; + + TRACE( "(%p,%p)\n",This,pmt ); + + if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Audio ) ) + return E_FAIL; + if ( !IsEqualGUID( &pmt->subtype, &MEDIASUBTYPE_PCM ) ) + return E_FAIL; + if ( !IsEqualGUID( &pmt->formattype, &FORMAT_WaveFormatEx ) ) + return E_FAIL; + if ( pmt->cbFormat < (sizeof(WAVEFORMATEX)-sizeof(WORD)) ) + return E_FAIL; + + pwfx = (const WAVEFORMATEX*)pmt->pbFormat; + if ( pwfx == NULL ) + return E_FAIL; + if ( pwfx->wFormatTag != 1 ) + return E_FAIL; + + return NOERROR; +} + +static HRESULT CAudioRendererPinImpl_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample ) +{ + CAudioRendererPinImpl_THIS(pImpl,pin); + HRESULT hr; + BYTE* pData = NULL; + DWORD dwDataLength; + DWORD dwWritten; + + FIXME( "(%p,%p)\n",This,pSample ); + + if ( !This->pRender->m_fWaveOutInit ) + return E_UNEXPECTED; + if ( This->pRender->m_fInFlush ) + return S_FALSE; + if ( pSample == NULL ) + return E_POINTER; + + hr = IMediaSample_GetPointer( pSample, &pData ); + if ( FAILED(hr) ) + return hr; + dwDataLength = (DWORD)IMediaSample_GetActualDataLength( pSample ); + + while ( 1 ) + { + TRACE("trying to write %lu bytes\n",dwDataLength); + + ResetEvent( This->pRender->m_hEventRender ); + hr = CAudioRendererImpl_waveOutWriteData( + This->pRender,pData,dwDataLength,&dwWritten); + if ( FAILED(hr) ) + break; + if ( hr == S_FALSE ) + { + WaitForSingleObject( This->pRender->m_hEventRender, INFINITE ); + continue; + } + pData += dwWritten; + dwDataLength -= dwWritten; + hr = CAudioRendererImpl_waveOutFlush(This->pRender); + if ( FAILED(hr) ) + break; + if ( dwDataLength == 0 ) + break; + } + + return hr; +} + +static HRESULT CAudioRendererPinImpl_ReceiveCanBlock( CPinBaseImpl* pImpl ) +{ + CAudioRendererPinImpl_THIS(pImpl,pin); + + TRACE( "(%p)\n", This ); + + /* might block. */ + return S_OK; +} + +static HRESULT CAudioRendererPinImpl_EndOfStream( CPinBaseImpl* pImpl ) +{ + CAudioRendererPinImpl_THIS(pImpl,pin); + + FIXME( "(%p)\n", This ); + + This->pRender->m_fInFlush = FALSE; + /* IMediaEventSink::Notify(EC_COMPLETE) */ + + return NOERROR; +} + +static HRESULT CAudioRendererPinImpl_BeginFlush( CPinBaseImpl* pImpl ) +{ + CAudioRendererPinImpl_THIS(pImpl,pin); + + FIXME( "(%p)\n", This ); + + This->pRender->m_fInFlush = TRUE; + CAudioRendererImpl_waveOutReset(This->pRender); + + return NOERROR; +} + +static HRESULT CAudioRendererPinImpl_EndFlush( CPinBaseImpl* pImpl ) +{ + CAudioRendererPinImpl_THIS(pImpl,pin); + + FIXME( "(%p)\n", This ); + + This->pRender->m_fInFlush = FALSE; + + return NOERROR; +} + +static HRESULT CAudioRendererPinImpl_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate ) +{ + CAudioRendererPinImpl_THIS(pImpl,pin); + + FIXME( "(%p)\n", This ); + + return NOERROR; +} + +static const CBasePinHandlers pinhandlers = +{ + CAudioRendererPinImpl_CheckMediaType, /* pCheckMediaType */ + NULL, /* pQualityNotify */ + CAudioRendererPinImpl_Receive, /* pReceive */ + CAudioRendererPinImpl_ReceiveCanBlock, /* pReceiveCanBlock */ + CAudioRendererPinImpl_EndOfStream, /* pEndOfStream */ + CAudioRendererPinImpl_BeginFlush, /* pBeginFlush */ + CAudioRendererPinImpl_EndFlush, /* pEndFlush */ + CAudioRendererPinImpl_NewSegment, /* pNewSegment */ +}; + + +/*************************************************************************** + * + * new/delete CAudioRendererImpl + * + */ + +/* can I use offsetof safely? - FIXME? */ +static QUARTZ_IFEntry FilterIFEntries[] = +{ + { &IID_IPersist, offsetof(CAudioRendererImpl,basefilter)-offsetof(CAudioRendererImpl,unk) }, + { &IID_IMediaFilter, offsetof(CAudioRendererImpl,basefilter)-offsetof(CAudioRendererImpl,unk) }, + { &IID_IBaseFilter, offsetof(CAudioRendererImpl,basefilter)-offsetof(CAudioRendererImpl,unk) }, + { &IID_IBasicAudio, offsetof(CAudioRendererImpl,basaud)-offsetof(CAudioRendererImpl,unk) }, +}; + +static void QUARTZ_DestroyAudioRenderer(IUnknown* punk) +{ + CAudioRendererImpl_THIS(punk,unk); + + TRACE( "(%p)\n", This ); + + if ( This->pPin != NULL ) + { + IUnknown_Release(This->pPin->unk.punkControl); + This->pPin = NULL; + } + + CAudioRendererImpl_UninitIBasicAudio(This); + CBaseFilterImpl_UninitIBaseFilter(&This->basefilter); +} + +HRESULT QUARTZ_CreateAudioRenderer(IUnknown* punkOuter,void** ppobj) +{ + CAudioRendererImpl* This = NULL; + HRESULT hr; + + TRACE("(%p,%p)\n",punkOuter,ppobj); + + This = (CAudioRendererImpl*) + QUARTZ_AllocObj( sizeof(CAudioRendererImpl) ); + if ( This == NULL ) + return E_OUTOFMEMORY; + This->pPin = NULL; + This->m_fInFlush = FALSE; + This->m_fWaveOutInit = FALSE; + This->m_hEventRender = (HANDLE)NULL; + + QUARTZ_IUnkInit( &This->unk, punkOuter ); + + hr = CBaseFilterImpl_InitIBaseFilter( + &This->basefilter, + This->unk.punkControl, + &CLSID_AudioRender, + QUARTZ_AudioRender_Name, + &filterhandlers ); + if ( SUCCEEDED(hr) ) + { + hr = CAudioRendererImpl_InitIBasicAudio(This); + if ( FAILED(hr) ) + { + CBaseFilterImpl_UninitIBaseFilter(&This->basefilter); + } + } + + if ( FAILED(hr) ) + { + QUARTZ_FreeObj(This); + return hr; + } + + This->unk.pEntries = FilterIFEntries; + This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]); + This->unk.pOnFinalRelease = QUARTZ_DestroyAudioRenderer; + + hr = QUARTZ_CreateAudioRendererPin( + This, + &This->basefilter.csFilter, + &This->pPin ); + if ( SUCCEEDED(hr) ) + hr = QUARTZ_CompList_AddComp( + This->basefilter.pInPins, + (IUnknown*)&This->pPin->pin, + NULL, 0 ); + if ( FAILED(hr) ) + { + IUnknown_Release( This->unk.punkControl ); + return hr; + } + + *ppobj = (void*)&(This->unk); + + return S_OK; +} + + +/*************************************************************************** + * + * new/delete CAudioRendererPinImpl + * + */ + +/* can I use offsetof safely? - FIXME? */ +static QUARTZ_IFEntry PinIFEntries[] = +{ + { &IID_IPin, offsetof(CAudioRendererPinImpl,pin)-offsetof(CAudioRendererPinImpl,unk) }, + { &IID_IMemInputPin, offsetof(CAudioRendererPinImpl,meminput)-offsetof(CAudioRendererPinImpl,unk) }, +}; + +static void QUARTZ_DestroyAudioRendererPin(IUnknown* punk) +{ + CAudioRendererPinImpl_THIS(punk,unk); + + TRACE( "(%p)\n", This ); + + CPinBaseImpl_UninitIPin( &This->pin ); + CMemInputPinBaseImpl_UninitIMemInputPin( &This->meminput ); +} + +HRESULT QUARTZ_CreateAudioRendererPin( + CAudioRendererImpl* pFilter, + CRITICAL_SECTION* pcsPin, + CAudioRendererPinImpl** ppPin) +{ + CAudioRendererPinImpl* This = NULL; + HRESULT hr; + + TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin); + + This = (CAudioRendererPinImpl*) + QUARTZ_AllocObj( sizeof(CAudioRendererPinImpl) ); + if ( This == NULL ) + return E_OUTOFMEMORY; + + QUARTZ_IUnkInit( &This->unk, NULL ); + This->pRender = pFilter; + + hr = CPinBaseImpl_InitIPin( + &This->pin, + This->unk.punkControl, + pcsPin, + &pFilter->basefilter, + QUARTZ_AudioRenderPin_Name, + FALSE, + &pinhandlers ); + + if ( SUCCEEDED(hr) ) + { + hr = CMemInputPinBaseImpl_InitIMemInputPin( + &This->meminput, + This->unk.punkControl, + &This->pin ); + if ( FAILED(hr) ) + { + CPinBaseImpl_UninitIPin( &This->pin ); + } + } + + if ( FAILED(hr) ) + { + QUARTZ_FreeObj(This); + return hr; + } + + This->unk.pEntries = PinIFEntries; + This->unk.dwEntries = sizeof(PinIFEntries)/sizeof(PinIFEntries[0]); + This->unk.pOnFinalRelease = QUARTZ_DestroyAudioRendererPin; + + *ppPin = This; + + TRACE("returned successfully.\n"); + + return S_OK; +} + + +/*************************************************************************** + * + * CAudioRendererImpl::IBasicAudio + * + */ + +static HRESULT WINAPI +IBasicAudio_fnQueryInterface(IBasicAudio* iface,REFIID riid,void** ppobj) +{ + CAudioRendererImpl_THIS(iface,basaud); + + TRACE("(%p)->()\n",This); + + return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj); +} + +static ULONG WINAPI +IBasicAudio_fnAddRef(IBasicAudio* iface) +{ + CAudioRendererImpl_THIS(iface,basaud); + + TRACE("(%p)->()\n",This); + + return IUnknown_AddRef(This->unk.punkControl); +} + +static ULONG WINAPI +IBasicAudio_fnRelease(IBasicAudio* iface) +{ + CAudioRendererImpl_THIS(iface,basaud); + + TRACE("(%p)->()\n",This); + + return IUnknown_Release(This->unk.punkControl); +} + +static HRESULT WINAPI +IBasicAudio_fnGetTypeInfoCount(IBasicAudio* iface,UINT* pcTypeInfo) +{ + CAudioRendererImpl_THIS(iface,basaud); + + FIXME("(%p)->()\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +IBasicAudio_fnGetTypeInfo(IBasicAudio* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj) +{ + CAudioRendererImpl_THIS(iface,basaud); + + FIXME("(%p)->()\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +IBasicAudio_fnGetIDsOfNames(IBasicAudio* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId) +{ + CAudioRendererImpl_THIS(iface,basaud); + + FIXME("(%p)->()\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +IBasicAudio_fnInvoke(IBasicAudio* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr) +{ + CAudioRendererImpl_THIS(iface,basaud); + + FIXME("(%p)->()\n",This); + + return E_NOTIMPL; +} + + +static HRESULT WINAPI +IBasicAudio_fnput_Volume(IBasicAudio* iface,long lVol) +{ + CAudioRendererImpl_THIS(iface,basaud); + + FIXME("(%p)->()\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +IBasicAudio_fnget_Volume(IBasicAudio* iface,long* plVol) +{ + CAudioRendererImpl_THIS(iface,basaud); + + FIXME("(%p)->()\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +IBasicAudio_fnput_Balance(IBasicAudio* iface,long lBalance) +{ + CAudioRendererImpl_THIS(iface,basaud); + + FIXME("(%p)->()\n",This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI +IBasicAudio_fnget_Balance(IBasicAudio* iface,long* plBalance) +{ + CAudioRendererImpl_THIS(iface,basaud); + + FIXME("(%p)->()\n",This); + + return E_NOTIMPL; +} + + +static ICOM_VTABLE(IBasicAudio) ibasicaudio = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + /* IUnknown fields */ + IBasicAudio_fnQueryInterface, + IBasicAudio_fnAddRef, + IBasicAudio_fnRelease, + /* IDispatch fields */ + IBasicAudio_fnGetTypeInfoCount, + IBasicAudio_fnGetTypeInfo, + IBasicAudio_fnGetIDsOfNames, + IBasicAudio_fnInvoke, + /* IBasicAudio fields */ + IBasicAudio_fnput_Volume, + IBasicAudio_fnget_Volume, + IBasicAudio_fnput_Balance, + IBasicAudio_fnget_Balance, +}; + + +HRESULT CAudioRendererImpl_InitIBasicAudio( CAudioRendererImpl* This ) +{ + TRACE("(%p)\n",This); + ICOM_VTBL(&This->basaud) = &ibasicaudio; + + return NOERROR; +} + +void CAudioRendererImpl_UninitIBasicAudio( CAudioRendererImpl* This ) +{ + TRACE("(%p)\n",This); +} + diff --git a/dlls/quartz/audren.h b/dlls/quartz/audren.h new file mode 100644 index 0000000000..26aa3c7642 --- /dev/null +++ b/dlls/quartz/audren.h @@ -0,0 +1,70 @@ +/* + * Audio Renderer (CLSID_AudioRender) + * + * FIXME + * - implements IRefereneceClock. + * + * hidenori@a2.ctktv.ne.jp + */ + +#ifndef WINE_DSHOW_AUDREN_H +#define WINE_DSHOW_AUDREN_H + +#include "iunk.h" +#include "basefilt.h" + +#define WINE_QUARTZ_WAVEOUT_COUNT 4 + +typedef struct CAudioRendererImpl CAudioRendererImpl; +typedef struct CAudioRendererPinImpl CAudioRendererPinImpl; + + +typedef struct AudRen_IBasicAudioImpl +{ + ICOM_VFIELD(IBasicAudio); +} AudRen_IBasicAudioImpl; + +struct CAudioRendererImpl +{ + QUARTZ_IUnkImpl unk; + CBaseFilterImpl basefilter; + AudRen_IBasicAudioImpl basaud; + + CAudioRendererPinImpl* pPin; + + BOOL m_fInFlush; + + /* for waveOut */ + BOOL m_fWaveOutInit; + HANDLE m_hEventRender; + HWAVEOUT m_hWaveOut; + DWORD m_dwBlockSize; + WAVEHDR* m_phdrCur; + WAVEHDR m_hdr[WINE_QUARTZ_WAVEOUT_COUNT]; +}; + +struct CAudioRendererPinImpl +{ + QUARTZ_IUnkImpl unk; + CPinBaseImpl pin; + CMemInputPinBaseImpl meminput; + + CAudioRendererImpl* pRender; +}; + +#define CAudioRendererImpl_THIS(iface,member) CAudioRendererImpl* This = ((CAudioRendererImpl*)(((char*)iface)-offsetof(CAudioRendererImpl,member))) +#define CAudioRendererPinImpl_THIS(iface,member) CAudioRendererPinImpl* This = ((CAudioRendererPinImpl*)(((char*)iface)-offsetof(CAudioRendererPinImpl,member))) + + +HRESULT CAudioRendererImpl_InitIBasicAudio( CAudioRendererImpl* This ); +void CAudioRendererImpl_UninitIBasicAudio( CAudioRendererImpl* This ); + +HRESULT QUARTZ_CreateAudioRenderer(IUnknown* punkOuter,void** ppobj); +HRESULT QUARTZ_CreateAudioRendererPin( + CAudioRendererImpl* pFilter, + CRITICAL_SECTION* pcsPin, + CAudioRendererPinImpl** ppPin); + + + +#endif /* WINE_DSHOW_AUDREN_H */ diff --git a/dlls/quartz/basefilt.c b/dlls/quartz/basefilt.c index 1bb40f86c0..ef1d57ee5e 100644 --- a/dlls/quartz/basefilt.c +++ b/dlls/quartz/basefilt.c @@ -73,54 +73,81 @@ static HRESULT WINAPI CBaseFilterImpl_fnStop(IBaseFilter* iface) { ICOM_THIS(CBaseFilterImpl,iface); + HRESULT hr; TRACE("(%p)->()\n",This); + hr = NOERROR; + EnterCriticalSection( &This->csFilter ); - /* FIXME - call OnStop() */ + if ( This->fstate == State_Running ) + { + if ( This->pHandlers->pOnInactive != NULL ) + hr = This->pHandlers->pOnInactive( This ); + } - This->fstate = State_Stopped; + if ( SUCCEEDED(hr) ) + This->fstate = State_Stopped; LeaveCriticalSection( &This->csFilter ); - return NOERROR; + return hr; } static HRESULT WINAPI CBaseFilterImpl_fnPause(IBaseFilter* iface) { ICOM_THIS(CBaseFilterImpl,iface); + HRESULT hr; TRACE("(%p)->()\n",This); + hr = NOERROR; + EnterCriticalSection( &This->csFilter ); - /* FIXME - call OnPause() */ + if ( This->fstate == State_Running ) + { + if ( This->pHandlers->pOnInactive != NULL ) + hr = This->pHandlers->pOnInactive( This ); + } - This->fstate = State_Paused; + if ( SUCCEEDED(hr) ) + This->fstate = State_Paused; LeaveCriticalSection( &This->csFilter ); - return NOERROR; + TRACE("hr = %08lx\n",hr); + + return hr; } static HRESULT WINAPI CBaseFilterImpl_fnRun(IBaseFilter* iface,REFERENCE_TIME rtStart) { ICOM_THIS(CBaseFilterImpl,iface); + HRESULT hr; TRACE("(%p)->()\n",This); + hr = NOERROR; + EnterCriticalSection( &This->csFilter ); - /* FIXME - call OnRun() */ - This->rtStart = rtStart; - This->fstate = State_Running; + + if ( This->fstate != State_Running ) + { + if ( This->pHandlers->pOnActive != NULL ) + hr = This->pHandlers->pOnActive( This ); + } + + if ( SUCCEEDED(hr) ) + This->fstate = State_Running; LeaveCriticalSection( &This->csFilter ); - return NOERROR; + return hr; } static HRESULT WINAPI @@ -136,6 +163,7 @@ CBaseFilterImpl_fnGetState(IBaseFilter* iface,DWORD dw,FILTER_STATE* pState) /* FIXME - ignore 'intermediate state' now */ EnterCriticalSection( &This->csFilter ); + TRACE("state %d\n",This->fstate); *pState = This->fstate; LeaveCriticalSection( &This->csFilter ); @@ -366,7 +394,8 @@ static ICOM_VTABLE(IBaseFilter) ibasefilter = HRESULT CBaseFilterImpl_InitIBaseFilter( CBaseFilterImpl* This, IUnknown* punkControl, - const CLSID* pclsidFilter, LPCWSTR lpwszNameGraph ) + const CLSID* pclsidFilter, LPCWSTR lpwszNameGraph, + const CBaseFilterHandlers* pHandlers ) { TRACE("(%p,%p)\n",This,punkControl); @@ -378,6 +407,7 @@ HRESULT CBaseFilterImpl_InitIBaseFilter( ICOM_VTBL(This) = &ibasefilter; This->punkControl = punkControl; + This->pHandlers = pHandlers; This->pclsidFilter = pclsidFilter; This->pInPins = NULL; This->pOutPins = NULL; @@ -394,6 +424,18 @@ HRESULT CBaseFilterImpl_InitIBaseFilter( return E_OUTOFMEMORY; memcpy( This->pwszNameGraph, lpwszNameGraph, This->cbNameGraph ); + This->pInPins = QUARTZ_CompList_Alloc(); + This->pOutPins = QUARTZ_CompList_Alloc(); + if ( This->pInPins == NULL || This->pOutPins == NULL ) + { + if ( This->pInPins != NULL ) + QUARTZ_CompList_Free(This->pInPins); + if ( This->pOutPins != NULL ) + QUARTZ_CompList_Free(This->pOutPins); + QUARTZ_FreeMem(This->pwszNameGraph); + return E_OUTOFMEMORY; + } + InitializeCriticalSection( &This->csFilter ); return NOERROR; @@ -415,7 +457,6 @@ void CBaseFilterImpl_UninitIBaseFilter( CBaseFilterImpl* This ) break; pPin = (IPin*)QUARTZ_CompList_GetItemPtr( pListItem ); QUARTZ_CompList_RemoveComp( This->pInPins, (IUnknown*)pPin ); - IPin_Release( pPin ); } QUARTZ_CompList_Free( This->pInPins ); @@ -430,7 +471,6 @@ void CBaseFilterImpl_UninitIBaseFilter( CBaseFilterImpl* This ) break; pPin = (IPin*)QUARTZ_CompList_GetItemPtr( pListItem ); QUARTZ_CompList_RemoveComp( This->pOutPins, (IUnknown*)pPin ); - IPin_Release( pPin ); } QUARTZ_CompList_Free( This->pOutPins ); diff --git a/dlls/quartz/basefilt.h b/dlls/quartz/basefilt.h index 1d1d0ced13..fe41a98f60 100644 --- a/dlls/quartz/basefilt.h +++ b/dlls/quartz/basefilt.h @@ -14,13 +14,20 @@ */ #include "complist.h" +#include "mtype.h" + +typedef struct CBaseFilterHandlers CBaseFilterHandlers; +typedef struct CBasePinHandlers CBasePinHandlers; + typedef struct CBaseFilterImpl { + /* IPersist - IMediaFilter - IBaseFilter */ ICOM_VFIELD(IBaseFilter); /* IUnknown fields */ IUnknown* punkControl; /* IBaseFilter fields */ + const CBaseFilterHandlers* pHandlers; CRITICAL_SECTION csFilter; const CLSID* pclsidFilter; QUARTZ_CompList* pInPins; /* a list of IPin-s. */ @@ -33,30 +40,44 @@ typedef struct CBaseFilterImpl FILTER_STATE fstate; } CBaseFilterImpl; +struct CBaseFilterHandlers +{ + HRESULT (*pOnActive)( CBaseFilterImpl* pImpl ); + HRESULT (*pOnInactive)( CBaseFilterImpl* pImpl ); +}; + + HRESULT CBaseFilterImpl_InitIBaseFilter( CBaseFilterImpl* This, IUnknown* punkControl, - const CLSID* pclsidFilter, LPCWSTR lpwszNameGraph ); + const CLSID* pclsidFilter, LPCWSTR lpwszNameGraph, + const CBaseFilterHandlers* pHandlers ); void CBaseFilterImpl_UninitIBaseFilter( CBaseFilterImpl* This ); /* - * Implements IPin and IMemInputPin. (internal) + * Implements IPin, IMemInputPin, and IQualityControl. (internal) * * a base class for implementing IPin. */ typedef struct CPinBaseImpl { + /* IPin */ ICOM_VFIELD(IPin); /* IUnknown fields */ IUnknown* punkControl; /* IPin fields */ + const CBasePinHandlers* pHandlers; DWORD cbIdLen; WCHAR* pwszId; BOOL bOutput; - CRITICAL_SECTION csPin; + /* you can change AcceptTypes while pcsPin has been hold */ + const AM_MEDIA_TYPE* pmtAcceptTypes; + ULONG cAcceptTypes; + + CRITICAL_SECTION* pcsPin; CBaseFilterImpl* pFilter; IPin* pPinConnectedTo; AM_MEDIA_TYPE* pmtConn; @@ -64,31 +85,66 @@ typedef struct CPinBaseImpl typedef struct CMemInputPinBaseImpl { + /* IMemInputPin */ ICOM_VFIELD(IMemInputPin); /* IUnknown fields */ IUnknown* punkControl; /* IMemInputPin fields */ - CRITICAL_SECTION* pcsPin; + CPinBaseImpl* pPin; IMemAllocator* pAllocator; BOOL bReadonly; } CMemInputPinBaseImpl; +typedef struct CQualityControlPassThruImpl +{ + /* IQualityControl */ + ICOM_VFIELD(IQualityControl); + + /* IUnknown fields */ + IUnknown* punkControl; + /* IQualityControl fields */ + CPinBaseImpl* pPin; + IQualityControl* pControl; +} CQualityControlPassThruImpl; + + +struct CBasePinHandlers +{ + HRESULT (*pCheckMediaType)( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt ); + HRESULT (*pQualityNotify)( CPinBaseImpl* pImpl, IBaseFilter* pFilter, Quality q ); + HRESULT (*pReceive)( CPinBaseImpl* pImpl, IMediaSample* pSample ); + HRESULT (*pReceiveCanBlock)( CPinBaseImpl* pImpl ); + HRESULT (*pEndOfStream)( CPinBaseImpl* pImpl ); + HRESULT (*pBeginFlush)( CPinBaseImpl* pImpl ); + HRESULT (*pEndFlush)( CPinBaseImpl* pImpl ); + HRESULT (*pNewSegment)( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate ); +}; + + HRESULT CPinBaseImpl_InitIPin( CPinBaseImpl* This, IUnknown* punkControl, + CRITICAL_SECTION* pcsPin, CBaseFilterImpl* pFilter, LPCWSTR pwszId, - BOOL bOutput ); + BOOL bOutput, + const CBasePinHandlers* pHandlers ); void CPinBaseImpl_UninitIPin( CPinBaseImpl* This ); HRESULT CMemInputPinBaseImpl_InitIMemInputPin( CMemInputPinBaseImpl* This, IUnknown* punkControl, - CRITICAL_SECTION* pcsPin - ); + CPinBaseImpl* pPin ); void CMemInputPinBaseImpl_UninitIMemInputPin( CMemInputPinBaseImpl* This ); +HRESULT CQualityControlPassThruImpl_InitIQualityControl( + CQualityControlPassThruImpl* This, IUnknown* punkControl, + CPinBaseImpl* pPin ); +void CQualityControlPassThruImpl_UninitIQualityControl( + CQualityControlPassThruImpl* This ); + + #endif /* WINE_DSHOW_BASEFILT_H */ diff --git a/dlls/quartz/basepin.c b/dlls/quartz/basepin.c index a1902df435..2571135345 100644 --- a/dlls/quartz/basepin.c +++ b/dlls/quartz/basepin.c @@ -21,7 +21,6 @@ DEFAULT_DEBUG_CHANNEL(quartz); #include "quartz_private.h" #include "basefilt.h" -#include "mtype.h" #include "memalloc.h" @@ -66,6 +65,7 @@ CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt) { ICOM_THIS(CPinBaseImpl,iface); HRESULT hr = E_NOTIMPL; + ULONG i; FIXME("(%p)->(%p,%p) stub!\n",This,pPin,pmt); @@ -74,7 +74,7 @@ CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt) if ( pPin == NULL || pmt == NULL ) return E_POINTER; - EnterCriticalSection( &This->csPin ); + EnterCriticalSection( This->pcsPin ); if ( This->pPinConnectedTo != NULL ) { @@ -84,11 +84,52 @@ CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt) /* FIXME - return fail if running */ - /* FIXME */ + if ( pmt != NULL ) + { + hr = IPin_QueryAccept(iface,pmt); + if ( FAILED(hr) ) + goto err; + hr = IPin_ReceiveConnection(pPin,iface,pmt); + if ( FAILED(hr) ) + goto err; + } + else + { + for ( i = 0; i < This->cAcceptTypes; i++ ) + { + pmt = &This->pmtAcceptTypes[i]; + hr = IPin_QueryAccept(iface,pmt); + if ( SUCCEEDED(hr) ) + { + hr = IPin_ReceiveConnection(pPin,iface,pmt); + if ( SUCCEEDED(hr) ) + { + goto connected; + } + } + } + + hr = VFW_E_TYPE_NOT_ACCEPTED; + goto err; + } + + if ( FAILED(hr) ) + goto err; + +connected:; + This->pmtConn = QUARTZ_MediaType_Duplicate( pmt ); + if ( This->pmtConn == NULL ) + { + hr = E_OUTOFMEMORY; + IPin_Disconnect(pPin); + goto err; + } + hr = S_OK; + + This->pPinConnectedTo = pPin; IPin_AddRef(pPin); - hr = E_NOTIMPL; err: - LeaveCriticalSection( &This->csPin ); + LeaveCriticalSection( This->pcsPin ); return hr; } @@ -106,7 +147,7 @@ CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt if ( pPin == NULL || pmt == NULL ) return E_POINTER; - EnterCriticalSection( &This->csPin ); + EnterCriticalSection( This->pcsPin ); if ( This->pPinConnectedTo != NULL ) { @@ -116,13 +157,24 @@ CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt /* FIXME - return fail if running */ - /* FIXME */ - hr = E_NOTIMPL; + hr = IPin_QueryAccept(iface,pmt); + if ( FAILED(hr) ) + goto err; + + This->pmtConn = QUARTZ_MediaType_Duplicate( pmt ); + if ( This->pmtConn == NULL ) + { + hr = E_OUTOFMEMORY; + goto err; + } + hr = S_OK; + + This->pPinConnectedTo = pPin; IPin_AddRef(pPin); err: - LeaveCriticalSection( &This->csPin ); + LeaveCriticalSection( This->pcsPin ); - return E_NOTIMPL; + return hr; } static HRESULT WINAPI @@ -133,7 +185,7 @@ CPinBaseImpl_fnDisconnect(IPin* iface) FIXME("(%p)->() stub!\n",This); - EnterCriticalSection( &This->csPin ); + EnterCriticalSection( This->pcsPin ); /* FIXME - return fail if running */ @@ -156,7 +208,7 @@ CPinBaseImpl_fnDisconnect(IPin* iface) hr = S_FALSE; /* FIXME - is this correct??? */ } - LeaveCriticalSection( &This->csPin ); + LeaveCriticalSection( This->pcsPin ); return hr; } @@ -172,7 +224,7 @@ CPinBaseImpl_fnConnectedTo(IPin* iface,IPin** ppPin) if ( ppPin == NULL ) return E_POINTER; - EnterCriticalSection( &This->csPin ); + EnterCriticalSection( This->pcsPin ); *ppPin = This->pPinConnectedTo; if ( This->pPinConnectedTo != NULL ) @@ -181,7 +233,7 @@ CPinBaseImpl_fnConnectedTo(IPin* iface,IPin** ppPin) hr = NOERROR; } - LeaveCriticalSection( &This->csPin ); + LeaveCriticalSection( This->pcsPin ); return hr; } @@ -197,7 +249,7 @@ CPinBaseImpl_fnConnectionMediaType(IPin* iface,AM_MEDIA_TYPE* pmt) if ( pmt == NULL ) return E_POINTER; - EnterCriticalSection( &This->csPin ); + EnterCriticalSection( This->pcsPin ); if ( This->pmtConn != NULL ) { @@ -211,7 +263,7 @@ CPinBaseImpl_fnConnectionMediaType(IPin* iface,AM_MEDIA_TYPE* pmt) hr = NOERROR; } - LeaveCriticalSection( &This->csPin ); + LeaveCriticalSection( This->pcsPin ); return hr; } @@ -226,7 +278,7 @@ CPinBaseImpl_fnQueryPinInfo(IPin* iface,PIN_INFO* pinfo) if ( pinfo == NULL ) return E_POINTER; - EnterCriticalSection( &This->csPin ); + EnterCriticalSection( This->pcsPin ); ZeroMemory( pinfo, sizeof(PIN_INFO) ); pinfo->pFilter = (IBaseFilter*)(This->pFilter); @@ -241,7 +293,7 @@ CPinBaseImpl_fnQueryPinInfo(IPin* iface,PIN_INFO* pinfo) pinfo->achName[sizeof(pinfo->achName)/sizeof(pinfo->achName[0])-1] = 0; } - LeaveCriticalSection( &This->csPin ); + LeaveCriticalSection( This->pcsPin ); return NOERROR; } @@ -283,20 +335,42 @@ static HRESULT WINAPI CPinBaseImpl_fnQueryAccept(IPin* iface,const AM_MEDIA_TYPE* pmt) { ICOM_THIS(CPinBaseImpl,iface); + HRESULT hr; - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->(%p)\n",This,pmt); - return E_NOTIMPL; + if ( pmt == NULL ) + return E_POINTER; + + hr = NOERROR; + EnterCriticalSection( This->pcsPin ); + if ( This->pHandlers->pCheckMediaType != NULL ) + hr = This->pHandlers->pCheckMediaType(This,pmt); + LeaveCriticalSection( This->pcsPin ); + + return hr; } static HRESULT WINAPI CPinBaseImpl_fnEnumMediaTypes(IPin* iface,IEnumMediaTypes** ppenum) { ICOM_THIS(CPinBaseImpl,iface); + HRESULT hr; - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->(%p)\n",This,ppenum); - return E_NOTIMPL; + if ( ppenum == NULL ) + return E_POINTER; + + hr = E_NOTIMPL; + + EnterCriticalSection( This->pcsPin ); + if ( This->cAcceptTypes > 0 ) + hr = QUARTZ_CreateEnumMediaTypes( + ppenum, This->pmtAcceptTypes, This->cAcceptTypes ); + LeaveCriticalSection( This->pcsPin ); + + return hr; } static HRESULT WINAPI @@ -314,52 +388,76 @@ static HRESULT WINAPI CPinBaseImpl_fnEndOfStream(IPin* iface) { ICOM_THIS(CPinBaseImpl,iface); + HRESULT hr = E_NOTIMPL; - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->()\n",This); if ( This->bOutput ) return E_UNEXPECTED; - return E_NOTIMPL; + EnterCriticalSection( This->pcsPin ); + if ( This->pHandlers->pEndOfStream != NULL ) + hr = This->pHandlers->pEndOfStream(This); + LeaveCriticalSection( This->pcsPin ); + + return hr; } static HRESULT WINAPI CPinBaseImpl_fnBeginFlush(IPin* iface) { ICOM_THIS(CPinBaseImpl,iface); + HRESULT hr = E_NOTIMPL; - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->()\n",This); if ( This->bOutput ) return E_UNEXPECTED; - return E_NOTIMPL; + EnterCriticalSection( This->pcsPin ); + if ( This->pHandlers->pBeginFlush != NULL ) + hr = This->pHandlers->pBeginFlush(This); + LeaveCriticalSection( This->pcsPin ); + + return hr; } static HRESULT WINAPI CPinBaseImpl_fnEndFlush(IPin* iface) { ICOM_THIS(CPinBaseImpl,iface); + HRESULT hr = E_NOTIMPL; - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->()\n",This); if ( This->bOutput ) return E_UNEXPECTED; - return E_NOTIMPL; + EnterCriticalSection( This->pcsPin ); + if ( This->pHandlers->pEndFlush != NULL ) + hr = This->pHandlers->pEndFlush(This); + LeaveCriticalSection( This->pcsPin ); + + return hr; } static HRESULT WINAPI CPinBaseImpl_fnNewSegment(IPin* iface,REFERENCE_TIME rtStart,REFERENCE_TIME rtStop,double rate) { ICOM_THIS(CPinBaseImpl,iface); + HRESULT hr = E_NOTIMPL; - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->()\n",This); if ( This->bOutput ) return E_UNEXPECTED; - return E_NOTIMPL; + EnterCriticalSection( This->pcsPin ); + if ( This->pHandlers->pNewSegment != NULL ) + hr = This->pHandlers->pNewSegment(This,rtStart,rtStop,rate); + LeaveCriticalSection( This->pcsPin ); + + return hr; } @@ -393,8 +491,10 @@ static ICOM_VTABLE(IPin) ipin = HRESULT CPinBaseImpl_InitIPin( CPinBaseImpl* This, IUnknown* punkControl, + CRITICAL_SECTION* pcsPin, CBaseFilterImpl* pFilter, LPCWSTR pwszId, - BOOL bOutput ) + BOOL bOutput, + const CBasePinHandlers* pHandlers ) { HRESULT hr = NOERROR; @@ -408,9 +508,13 @@ HRESULT CPinBaseImpl_InitIPin( ICOM_VTBL(This) = &ipin; This->punkControl = punkControl; + This->pHandlers = pHandlers; This->cbIdLen = sizeof(WCHAR)*(strlenW(pwszId)+1); This->pwszId = NULL; This->bOutput = bOutput; + This->pmtAcceptTypes = NULL; + This->cAcceptTypes = 0; + This->pcsPin = pcsPin; This->pFilter = pFilter; This->pPinConnectedTo = NULL; This->pmtConn = NULL; @@ -421,8 +525,7 @@ HRESULT CPinBaseImpl_InitIPin( hr = E_OUTOFMEMORY; goto err; } - - InitializeCriticalSection( &This->csPin ); + memcpy( This->pwszId, pwszId, This->cbIdLen ); return NOERROR; @@ -442,8 +545,6 @@ void CPinBaseImpl_UninitIPin( CPinBaseImpl* This ) QUARTZ_FreeMem( This->pwszId ); This->pwszId = NULL; } - - DeleteCriticalSection( &This->csPin ); } @@ -497,7 +598,7 @@ CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin* iface,IMemAllocator** ppAlloca if ( ppAllocator == NULL ) return E_POINTER; - EnterCriticalSection( This->pcsPin ); + EnterCriticalSection( This->pPin->pcsPin ); if ( This->pAllocator == NULL ) { @@ -516,7 +617,7 @@ CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin* iface,IMemAllocator** ppAlloca IMemAllocator_AddRef(This->pAllocator); } - LeaveCriticalSection( This->pcsPin ); + LeaveCriticalSection( This->pPin->pcsPin ); return hr; } @@ -531,7 +632,7 @@ CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin* iface,IMemAllocator* pAlloc if ( pAllocator == NULL ) return E_POINTER; - EnterCriticalSection( This->pcsPin ); + EnterCriticalSection( This->pPin->pcsPin ); if ( This->pAllocator != NULL ) { @@ -543,7 +644,7 @@ CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin* iface,IMemAllocator* pAlloc This->bReadonly = bReadonly; - LeaveCriticalSection( This->pcsPin ); + LeaveCriticalSection( This->pPin->pcsPin ); return NOERROR; } @@ -566,10 +667,16 @@ static HRESULT WINAPI CMemInputPinBaseImpl_fnReceive(IMemInputPin* iface,IMediaSample* pSample) { ICOM_THIS(CMemInputPinBaseImpl,iface); + HRESULT hr = E_NOTIMPL; - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->(%p)\n",This,pSample); - return E_NOTIMPL; + EnterCriticalSection( This->pPin->pcsPin ); + if ( This->pPin->pHandlers->pReceive != NULL ) + hr = This->pPin->pHandlers->pReceive(This->pPin,pSample); + LeaveCriticalSection( This->pPin->pcsPin ); + + return hr; } static HRESULT WINAPI @@ -584,7 +691,7 @@ CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSamp if ( ppSample == NULL || pnSampleProcessed == NULL ) return E_POINTER; - EnterCriticalSection( This->pcsPin ); + EnterCriticalSection( This->pPin->pcsPin ); hr = NOERROR; for ( n = 0; n < nSample; n++ ) @@ -594,7 +701,7 @@ CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSamp break; } - LeaveCriticalSection( This->pcsPin ); + LeaveCriticalSection( This->pPin->pcsPin ); *pnSampleProcessed = n; return hr; @@ -604,10 +711,16 @@ static HRESULT WINAPI CMemInputPinBaseImpl_fnReceiveCanBlock(IMemInputPin* iface) { ICOM_THIS(CMemInputPinBaseImpl,iface); + HRESULT hr = E_NOTIMPL; - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->()\n",This); - return E_NOTIMPL; + EnterCriticalSection( This->pPin->pcsPin ); + if ( This->pPin->pHandlers->pReceiveCanBlock != NULL ) + hr = This->pPin->pHandlers->pReceiveCanBlock(This->pPin); + LeaveCriticalSection( This->pPin->pcsPin ); + + return hr; } @@ -629,8 +742,7 @@ static ICOM_VTABLE(IMemInputPin) imeminputpin = HRESULT CMemInputPinBaseImpl_InitIMemInputPin( CMemInputPinBaseImpl* This, IUnknown* punkControl, - CRITICAL_SECTION* pcsPin - ) + CPinBaseImpl* pPin ) { TRACE("(%p,%p)\n",This,punkControl); @@ -642,7 +754,7 @@ HRESULT CMemInputPinBaseImpl_InitIMemInputPin( ICOM_VTBL(This) = &imeminputpin; This->punkControl = punkControl; - This->pcsPin = pcsPin; + This->pPin = pPin; This->pAllocator = NULL; This->bReadonly = FALSE; @@ -661,4 +773,107 @@ void CMemInputPinBaseImpl_UninitIMemInputPin( } } +/*************************************************************************** + * + * CQualityControlPassThruImpl + * + */ + +static HRESULT WINAPI +CQualityControlPassThruImpl_fnQueryInterface(IQualityControl* iface,REFIID riid,void** ppobj) +{ + ICOM_THIS(CQualityControlPassThruImpl,iface); + + TRACE("(%p)->()\n",This); + + return IUnknown_QueryInterface(This->punkControl,riid,ppobj); +} + +static ULONG WINAPI +CQualityControlPassThruImpl_fnAddRef(IQualityControl* iface) +{ + ICOM_THIS(CQualityControlPassThruImpl,iface); + + TRACE("(%p)->()\n",This); + + return IUnknown_AddRef(This->punkControl); +} + +static ULONG WINAPI +CQualityControlPassThruImpl_fnRelease(IQualityControl* iface) +{ + ICOM_THIS(CQualityControlPassThruImpl,iface); + + TRACE("(%p)->()\n",This); + + return IUnknown_Release(This->punkControl); +} + + +static HRESULT WINAPI +CQualityControlPassThruImpl_fnNotify(IQualityControl* iface,IBaseFilter* pFilter,Quality q) +{ + ICOM_THIS(CQualityControlPassThruImpl,iface); + HRESULT hr = S_FALSE; + + TRACE("(%p)->()\n",This); + + if ( This->pControl != NULL ) + return IQualityControl_Notify( This->pControl, pFilter, q ); + + EnterCriticalSection( This->pPin->pcsPin ); + if ( This->pPin->pHandlers->pQualityNotify != NULL ) + hr = This->pPin->pHandlers->pQualityNotify(This->pPin,pFilter,q); + LeaveCriticalSection( This->pPin->pcsPin ); + + return hr; +} + +static HRESULT WINAPI +CQualityControlPassThruImpl_fnSetSink(IQualityControl* iface,IQualityControl* pControl) +{ + ICOM_THIS(CQualityControlPassThruImpl,iface); + + TRACE("(%p)->()\n",This); + + This->pControl = pControl; /* AddRef() must not be called */ + + return NOERROR; +} + +static ICOM_VTABLE(IQualityControl) iqualitycontrol = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + /* IUnknown fields */ + CQualityControlPassThruImpl_fnQueryInterface, + CQualityControlPassThruImpl_fnAddRef, + CQualityControlPassThruImpl_fnRelease, + /* IQualityControl fields */ + CQualityControlPassThruImpl_fnNotify, + CQualityControlPassThruImpl_fnSetSink, +}; + +HRESULT CQualityControlPassThruImpl_InitIQualityControl( + CQualityControlPassThruImpl* This, IUnknown* punkControl, + CPinBaseImpl* pPin ) +{ + TRACE("(%p,%p)\n",This,punkControl); + + if ( punkControl == NULL ) + { + ERR( "punkControl must not be NULL\n" ); + return E_INVALIDARG; + } + + ICOM_VTBL(This) = &iqualitycontrol; + This->punkControl = punkControl; + This->pPin = pPin; + + return NOERROR; +} + +void CQualityControlPassThruImpl_UninitIQualityControl( + CQualityControlPassThruImpl* This ) +{ +} diff --git a/dlls/quartz/fgevent.c b/dlls/quartz/fgevent.c index db47c09c91..2d25a358f1 100644 --- a/dlls/quartz/fgevent.c +++ b/dlls/quartz/fgevent.c @@ -25,7 +25,7 @@ DEFAULT_DEBUG_CHANNEL(quartz); #include "quartz_private.h" #include "fgraph.h" -#define EVENTQUEUE_BLOCKSIZE 16 +#define EVENTQUEUE_BLOCKSIZE 2 #define EVENTQUEUE_MAX 1024 struct FilterGraph_MEDIAEVENT @@ -36,6 +36,106 @@ struct FilterGraph_MEDIAEVENT }; +static HRESULT FGEVENT_KeepEvent( + BOOL bKeep, + long lEventCode, LONG_PTR lParam1, LONG_PTR lParam2 ) +{ + switch ( lEventCode ) + { + /*case EC_COMPLETE:*/ + case EC_USERABORT: + break; + case EC_ERRORABORT: + break; + case EC_TIME: + break; + /*case EC_REPAINT:*/ + case EC_STREAM_ERROR_STOPPED: + break; + case EC_STREAM_ERROR_STILLPLAYING: + break; + case EC_ERROR_STILLPLAYING: + break; + case EC_PALETTE_CHANGED: + break; + case EC_VIDEO_SIZE_CHANGED: + break; + case EC_QUALITY_CHANGE: + break; + /*case EC_SHUTTING_DOWN:*/ + case EC_CLOCK_CHANGED: + break; + case EC_PAUSED: + break; + + case EC_OPENING_FILE: + break; + case EC_BUFFERING_DATA: + break; + case EC_FULLSCREEN_LOST: + if ( bKeep ) + { + if ( ((IBaseFilter*)lParam2) != NULL ) + IBaseFilter_AddRef( (IBaseFilter*)lParam2 ); + } + else + { + if ( ((IBaseFilter*)lParam2) != NULL ) + IBaseFilter_Release( (IBaseFilter*)lParam2 ); + } + break; + /*case EC_ACTIVATE:*/ + /*case EC_NEED_RESTART:*/ + /*case EC_WINDOW_DESTROYED:*/ + /*case EC_DISPLAY_CHANGED:*/ + /*case EC_STARVATION:*/ + /*case EC_OLE_EVENT:*/ + /*case EC_NOTIFY_WINDOW:*/ + /*case EC_STREAM_CONTROL_STOPPED:*/ + /*case EC_STREAM_CONTROL_STARTED:*/ + /*case EC_END_OF_SEGMENT:*/ + /*case EC_SEGMENT_STARTED:*/ + case EC_LENGTH_CHANGED: + break; + case EC_DEVICE_LOST: + if ( bKeep ) + { + if ( ((IUnknown*)lParam1) != NULL ) + IUnknown_AddRef( (IUnknown*)lParam1 ); + } + else + { + if ( ((IUnknown*)lParam1) != NULL ) + IUnknown_Release( (IUnknown*)lParam1 ); + } + break; + + case EC_STEP_COMPLETE: + break; + case EC_SKIP_FRAMES: + break; + + /*case EC_TIMECODE_AVAILABLE:*/ + /*case EC_EXTDEVICE_MODE_CHANGE:*/ + + case EC_GRAPH_CHANGED: + break; + case EC_CLOCK_UNSET: + break; + + default: + if ( lEventCode < EC_USER ) + { + FIXME( "unknown system event %08lx\n", lEventCode ); + return E_INVALIDARG; + } + TRACE( "user event %08lx\n", lEventCode ); + break; + } + + return NOERROR; +} + /*************************************************************************** * * CLSID_FilterGraph::IMediaEvent[Ex] @@ -129,7 +229,7 @@ static HRESULT WINAPI IMediaEventEx_fnGetEvent(IMediaEventEx* iface,long* plEventCode,LONG_PTR* plParam1,LONG_PTR* plParam2,long lTimeOut) { CFilterGraph_THIS(iface,mediaevent); - ULONG cbQueued; + ULONG cQueued; DWORD dw; DWORD dwStart; HRESULT hr; @@ -154,11 +254,11 @@ IMediaEventEx_fnGetEvent(IMediaEventEx* iface,long* plEventCode,LONG_PTR* plPara hr = S_FALSE; if ( This->m_cbMediaEventsMax > 0 ) { - cbQueued = + cQueued = (This->m_cbMediaEventsMax + This->m_cbMediaEventsPut - This->m_cbMediaEventsGet) % This->m_cbMediaEventsMax; - if ( cbQueued > 0 ) + if ( cQueued > 0 ) { pEvent = &This->m_pMediaEvents[This->m_cbMediaEventsGet]; *plEventCode = pEvent->lEventCode; @@ -168,6 +268,8 @@ IMediaEventEx_fnGetEvent(IMediaEventEx* iface,long* plEventCode,LONG_PTR* plPara This->m_cbMediaEventsMax; hr = NOERROR; + if ( This->m_cbMediaEventsPut == This->m_cbMediaEventsGet ) + ResetEvent( This->m_hMediaEvent ); } } LeaveCriticalSection( &This->m_csMediaEvents ); @@ -259,9 +361,9 @@ IMediaEventEx_fnFreeEventParams(IMediaEventEx* iface,long lEventCode,LONG_PTR lP { CFilterGraph_THIS(iface,mediaevent); - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->(%08lx,%08x,%08x)\n",This,lEventCode,lParam1,lParam2); - return E_NOTIMPL; + return FGEVENT_KeepEvent( FALSE, lEventCode, lParam1, lParam2 ); } static HRESULT WINAPI @@ -269,9 +371,15 @@ IMediaEventEx_fnSetNotifyWindow(IMediaEventEx* iface,OAHWND hwnd,long message,LO { CFilterGraph_THIS(iface,mediaevent); - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->(%08x,%08lx,%08x)\n",This,hwnd,message,lParam); - return E_NOTIMPL; + EnterCriticalSection( &This->m_csMediaEvents ); + This->m_hwndEventNotify = (HWND)hwnd; + This->m_lEventNotifyMsg = message; + This->m_lEventNotifyParam = lParam; + LeaveCriticalSection( &This->m_csMediaEvents ); + + return NOERROR; } static HRESULT WINAPI @@ -279,9 +387,16 @@ IMediaEventEx_fnSetNotifyFlags(IMediaEventEx* iface,long lNotifyFlags) { CFilterGraph_THIS(iface,mediaevent); - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->(%ld)\n",This,lNotifyFlags); - return E_NOTIMPL; + if ( lNotifyFlags != 0 && lNotifyFlags != 1 ) + return E_INVALIDARG; + + EnterCriticalSection( &This->m_csMediaEvents ); + This->m_lEventNotifyFlags = lNotifyFlags; + LeaveCriticalSection( &This->m_csMediaEvents ); + + return NOERROR; } static HRESULT WINAPI @@ -289,9 +404,16 @@ IMediaEventEx_fnGetNotifyFlags(IMediaEventEx* iface,long* plNotifyFlags) { CFilterGraph_THIS(iface,mediaevent); - FIXME("(%p)->() stub!\n",This); + TRACE("(%p)->(%p)\n",This,plNotifyFlags); - return E_NOTIMPL; + if ( plNotifyFlags == NULL ) + return E_POINTER; + + EnterCriticalSection( &This->m_csMediaEvents ); + *plNotifyFlags = This->m_lEventNotifyFlags; + LeaveCriticalSection( &This->m_csMediaEvents ); + + return NOERROR; } @@ -336,6 +458,10 @@ HRESULT CFilterGraph_InitIMediaEventEx( CFilterGraph* pfg ) pfg->m_cbMediaEventsPut = 0; pfg->m_cbMediaEventsGet = 0; pfg->m_cbMediaEventsMax = 0; + pfg->m_hwndEventNotify = (HWND)NULL; + pfg->m_lEventNotifyMsg = 0; + pfg->m_lEventNotifyParam = 0; + pfg->m_lEventNotifyFlags = 0; return NOERROR; } @@ -411,10 +537,98 @@ static HRESULT WINAPI IMediaEventSink_fnNotify(IMediaEventSink* iface,long lEventCode,LONG_PTR lParam1,LONG_PTR lParam2) { CFilterGraph_THIS(iface,mediaeventsink); + HRESULT hr = NOERROR; + ULONG cQueued; + ULONG cTemp; + FilterGraph_MEDIAEVENT* pEvent; - FIXME("(%p)->(%ld,%08x,%08x) stub!\n",This,lEventCode,lParam1,lParam2); + TRACE("(%p)->(%08lx,%08x,%08x) stub!\n",This,lEventCode,lParam1,lParam2); - return E_NOTIMPL; + EnterCriticalSection( &This->m_csMediaEvents ); + + /* allocate a new entry. */ + if ( This->m_cbMediaEventsMax == 0 ) + cQueued = 0; + else + cQueued = + (This->m_cbMediaEventsMax + + This->m_cbMediaEventsPut - This->m_cbMediaEventsGet) % + This->m_cbMediaEventsMax; + + if ( (cQueued + 1) >= This->m_cbMediaEventsMax ) + { + if ( This->m_cbMediaEventsMax >= EVENTQUEUE_MAX ) + { + hr = E_FAIL; + goto end; + } + pEvent = (FilterGraph_MEDIAEVENT*) + QUARTZ_AllocMem( sizeof(FilterGraph_MEDIAEVENT) * + (This->m_cbMediaEventsMax+EVENTQUEUE_BLOCKSIZE) ); + if ( pEvent == NULL ) + { + hr = E_OUTOFMEMORY; + goto end; + } + if ( cQueued > 0 ) + { + if ( (This->m_cbMediaEventsGet + cQueued) >= + This->m_cbMediaEventsMax ) + { + cTemp = This->m_cbMediaEventsMax - This->m_cbMediaEventsGet; + memcpy( + pEvent, + &This->m_pMediaEvents[This->m_cbMediaEventsGet], + sizeof(FilterGraph_MEDIAEVENT) * cTemp ); + memcpy( + pEvent + cTemp, + &This->m_pMediaEvents[0], + sizeof(FilterGraph_MEDIAEVENT) * (cQueued - cTemp) ); + } + else + { + memcpy( + pEvent, + &This->m_pMediaEvents[This->m_cbMediaEventsGet], + sizeof(FilterGraph_MEDIAEVENT) * cQueued ); + } + QUARTZ_FreeMem( This->m_pMediaEvents ); + } + This->m_pMediaEvents = pEvent; + This->m_cbMediaEventsMax += EVENTQUEUE_BLOCKSIZE; + This->m_cbMediaEventsPut = cQueued; + This->m_cbMediaEventsGet = 0; + } + + /* duplicate params if necessary. */ + hr = FGEVENT_KeepEvent( TRUE, lEventCode, lParam1, lParam2 ); + if ( FAILED(hr) ) + goto end; + + /* add to the queue. */ + pEvent = &This->m_pMediaEvents[This->m_cbMediaEventsPut]; + pEvent->lEventCode = lEventCode; + pEvent->lParam1 = lParam1; + pEvent->lParam2 = lParam2; + This->m_cbMediaEventsPut = + (This->m_cbMediaEventsPut + 1) % This->m_cbMediaEventsMax; + + SetEvent( This->m_hMediaEvent ); + if ( This->m_hwndEventNotify != (HWND)NULL && + This->m_lEventNotifyFlags == 0 ) + { + PostMessageA( + This->m_hwndEventNotify, + This->m_lEventNotifyMsg, + (WPARAM)0, + (LPARAM)This->m_lEventNotifyParam ); + } + + hr = NOERROR; +end: + LeaveCriticalSection( &This->m_csMediaEvents ); + + return hr; } diff --git a/dlls/quartz/fgraph.h b/dlls/quartz/fgraph.h index cdbd5d55d6..9329820417 100644 --- a/dlls/quartz/fgraph.h +++ b/dlls/quartz/fgraph.h @@ -140,6 +140,10 @@ typedef struct CFilterGraph ULONG m_cbMediaEventsPut; ULONG m_cbMediaEventsGet; ULONG m_cbMediaEventsMax; + HWND m_hwndEventNotify; + long m_lEventNotifyMsg; + LONG_PTR m_lEventNotifyParam; + long m_lEventNotifyFlags; /* IMediaEventSink fields. */ /* IMediaPosition fields. */ /* IMediaSeeking fields. */ diff --git a/dlls/quartz/ifgraph.c b/dlls/quartz/ifgraph.c index ecff0de838..ae807475ce 100644 --- a/dlls/quartz/ifgraph.c +++ b/dlls/quartz/ifgraph.c @@ -80,6 +80,20 @@ static HRESULT CFilterGraph_DisconnectAllPins( IBaseFilter* pFilter ) } +static HRESULT CFilterGraph_GraphChanged( CFilterGraph* This ) +{ + /* IDistributorNotify_NotifyGraphChange() */ + + IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This), + EC_GRAPH_CHANGED, 0, 0); + EnterCriticalSection( &This->m_csGraphVersion ); + This->m_lGraphVersion ++; + LeaveCriticalSection( &This->m_csGraphVersion ); + + return NOERROR; +} + + /****************************************************************************/ static HRESULT WINAPI @@ -220,12 +234,9 @@ name_ok: goto end; } - /* IDistributorNotify_NotifyGraphChange() */ - IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This), - EC_GRAPH_CHANGED, 0, 0); - EnterCriticalSection( &This->m_csGraphVersion ); - This->m_lGraphVersion ++; - LeaveCriticalSection( &This->m_csGraphVersion ); + hr = CFilterGraph_GraphChanged(This); + if ( FAILED(hr) ) + goto end; hr = hrSucceeded; end: @@ -269,12 +280,9 @@ IFilterGraph2_fnRemoveFilter(IFilterGraph2* iface,IBaseFilter* pFilter) This->m_pFilterList, (IUnknown*)pFilter ); } - /* IDistributorNotify_NotifyGraphChange() */ - IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This), - EC_GRAPH_CHANGED, 0, 0); - EnterCriticalSection( &This->m_csGraphVersion ); - This->m_lGraphVersion ++; - LeaveCriticalSection( &This->m_csGraphVersion ); + hr = CFilterGraph_GraphChanged(This); + if ( FAILED(hr) ) + goto end; end:; QUARTZ_CompList_Unlock( This->m_pFilterList ); @@ -403,12 +411,9 @@ IFilterGraph2_fnConnectDirect(IFilterGraph2* iface,IPin* pOut,IPin* pIn,const AM goto end; } - /* IDistributorNotify_NotifyGraphChange() */ - IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This), - EC_GRAPH_CHANGED, 0, 0); - EnterCriticalSection( &This->m_csGraphVersion ); - This->m_lGraphVersion ++; - LeaveCriticalSection( &This->m_csGraphVersion ); + hr = CFilterGraph_GraphChanged(This); + if ( FAILED(hr) ) + goto end; end: QUARTZ_CompList_Unlock( This->m_pFilterList ); @@ -454,14 +459,14 @@ IFilterGraph2_fnDisconnect(IFilterGraph2* iface,IPin* pPin) IPin_Release(pConnTo); } hr = IPin_Disconnect(pPin); + if ( FAILED(hr) ) + goto end; - /* IDistributorNotify_NotifyGraphChange() */ - IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This), - EC_GRAPH_CHANGED, 0, 0); - EnterCriticalSection( &This->m_csGraphVersion ); - This->m_lGraphVersion ++; - LeaveCriticalSection( &This->m_csGraphVersion ); + hr = CFilterGraph_GraphChanged(This); + if ( FAILED(hr) ) + goto end; +end: QUARTZ_CompList_Unlock( This->m_pFilterList ); return hr; @@ -657,17 +662,13 @@ static HRESULT WINAPI IFilterGraph2_fnReconnectEx(IFilterGraph2* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt) { CFilterGraph_THIS(iface,fgraph); + HRESULT hr; FIXME( "(%p)->(%p,%p) stub!\n",This,pPin,pmt ); /* reconnect asynchronously. */ - /* IDistributorNotify_NotifyGraphChange() */ - IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This), - EC_GRAPH_CHANGED, 0, 0); - EnterCriticalSection( &This->m_csGraphVersion ); - This->m_lGraphVersion ++; - LeaveCriticalSection( &This->m_csGraphVersion ); + hr = CFilterGraph_GraphChanged(This); return E_NOTIMPL; } diff --git a/dlls/quartz/imfilter.c b/dlls/quartz/imfilter.c index bafb5534e0..a602852ea2 100644 --- a/dlls/quartz/imfilter.c +++ b/dlls/quartz/imfilter.c @@ -348,12 +348,8 @@ IMediaFilter_fnSetSyncSource(IMediaFilter* iface,IReferenceClock* pobjClock) QUARTZ_CompList_Unlock( This->m_pFilterList ); - if ( This->m_pClock != NULL ) - IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This), - EC_CLOCK_CHANGED, 0, 0); - else - IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This), - EC_CLOCK_UNSET, 0, 0); + IMediaEventSink_Notify(CFilterGraph_IMediaEventSink(This), + EC_CLOCK_CHANGED, 0, 0); LeaveCriticalSection( &This->m_csClock ); diff --git a/dlls/quartz/main.c b/dlls/quartz/main.c index e10e47c559..9b73116f7d 100644 --- a/dlls/quartz/main.c +++ b/dlls/quartz/main.c @@ -12,6 +12,7 @@ #include "wingdi.h" #include "winuser.h" #include "winnls.h" +#include "mmsystem.h" #include "ole2.h" #include "wine/obj_oleaut.h" #include "strmif.h" @@ -30,6 +31,7 @@ DEFAULT_DEBUG_CHANNEL(quartz); #include "fmap.h" #include "fmap2.h" #include "seekpass.h" +#include "audren.h" typedef struct QUARTZ_CLASSENTRY @@ -74,6 +76,7 @@ static const QUARTZ_CLASSENTRY QUARTZ_ClassList[] = { &CLSID_FilterMapper, &QUARTZ_CreateFilterMapper }, { &CLSID_FilterMapper2, &QUARTZ_CreateFilterMapper2 }, { &CLSID_SeekingPassThru, &QUARTZ_CreateSeekingPassThru }, + { &CLSID_AudioRender, &QUARTZ_CreateAudioRenderer }, { NULL, NULL }, }; @@ -292,6 +295,8 @@ BOOL WINAPI QUARTZ_DllMain( DWORD fdwReason, LPVOID lpvReserved ) { + TRACE("(%08x,%08lx,%p)\n",hInstDLL,fdwReason,lpvReserved); + switch ( fdwReason ) { case DLL_PROCESS_ATTACH: diff --git a/dlls/quartz/memalloc.c b/dlls/quartz/memalloc.c index 6c2b473925..59a9c508e4 100644 --- a/dlls/quartz/memalloc.c +++ b/dlls/quartz/memalloc.c @@ -287,6 +287,10 @@ IMemAllocator_fnDecommit(IMemAllocator* iface) if ( !bBlock ) { + QUARTZ_FreeMem(This->ppSamples); + This->ppSamples = NULL; + QUARTZ_FreeMem(This->pData); + This->pData = NULL; hr = NOERROR; break; } diff --git a/dlls/quartz/quartz.spec b/dlls/quartz/quartz.spec index ca27c85082..64e49260be 100644 --- a/dlls/quartz/quartz.spec +++ b/dlls/quartz/quartz.spec @@ -4,7 +4,7 @@ init QUARTZ_DllMain import oleaut32.dll import ole32.dll -#import winmm.dll +import winmm.dll import user32.dll #import gdi32.dll import advapi32.dll diff --git a/dlls/quartz/sample.c b/dlls/quartz/sample.c index 8094164d50..03a8f0e30c 100644 --- a/dlls/quartz/sample.c +++ b/dlls/quartz/sample.c @@ -491,6 +491,8 @@ HRESULT QUARTZ_CreateMemMediaSample( void QUARTZ_DestroyMemMediaSample( CMemMediaSample* pSample ) { + TRACE("(%p)\n",pSample); + QUARTZ_FreeObj( pSample ); } diff --git a/include/strmif.h b/include/strmif.h index 293b550b90..9176e66efb 100644 --- a/include/strmif.h +++ b/include/strmif.h @@ -1331,7 +1331,7 @@ ICOM_DEFINE(IMediaSample,IUnknown) #define IMediaSample_SetSyncPoint(p,a1) ICOM_CALL1(SetSyncPoint,p,a1) #define IMediaSample_IsPreroll(p) ICOM_CALL (IsPreroll,p) #define IMediaSample_SetPreroll(p,a1) ICOM_CALL1(SetPreroll,p,a1) -#define IMediaSample_GetActualDataLength(p,a1) ICOM_CALL1(GetActualDataLength,p,a1) +#define IMediaSample_GetActualDataLength(p) ICOM_CALL (GetActualDataLength,p) #define IMediaSample_SetActualDataLength(p,a1) ICOM_CALL1(SetActualDataLength,p,a1) #define IMediaSample_GetMediaType(p,a1) ICOM_CALL1(GetMediaType,p,a1) #define IMediaSample_SetMediaType(p,a1) ICOM_CALL1(SetMediaType,p,a1) diff --git a/winedefault.reg b/winedefault.reg index 46ba9b1d41..9dd68f3c33 100644 --- a/winedefault.reg +++ b/winedefault.reg @@ -318,6 +318,16 @@ "FriendlyName"="Audio Renderers" +# CLSID_AudioRender + +[HKEY_CLASSES_ROOT\CLSID\{e30629d1-27e5-11ce-875d-00608cb78066}\InprocServer32] +@="quartz.dll" +"ThreadingModel"="Both" + +[HKEY_CLASSES_ROOT\CLSID\{E0F158E1-CB04-11D0-BD4E-00A0C911CE86}\Instance\{e30629d1-27e5-11ce-875d-00608cb78066}] +"CLSID"="{e30629d1-27e5-11ce-875d-00608cb78066}" +"FriendlyName"="Waveout audio renderer" + # # Entries for Mozilla ActiveX control support