/* * Implementation of CLSID_SeekingPassThru * * FIXME - not tested yet. * * hidenori@a2.ctktv.ne.jp */ #include "config.h" #include "windef.h" #include "winbase.h" #include "wingdi.h" #include "winuser.h" #include "winerror.h" #include "strmif.h" #include "control.h" #include "uuids.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(quartz); #include "quartz_private.h" #include "seekpass.h" /*************************************************************************** * * CSeekingPassThru::ISeekingPassThru * */ static HRESULT WINAPI ISeekingPassThru_fnQueryInterface(ISeekingPassThru* iface,REFIID riid,void** ppobj) { CSeekingPassThru_THIS(iface,seekpass); TRACE("(%p)->()\n",This); return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj); } static ULONG WINAPI ISeekingPassThru_fnAddRef(ISeekingPassThru* iface) { CSeekingPassThru_THIS(iface,seekpass); TRACE("(%p)->()\n",This); return IUnknown_AddRef(This->unk.punkControl); } static ULONG WINAPI ISeekingPassThru_fnRelease(ISeekingPassThru* iface) { CSeekingPassThru_THIS(iface,seekpass); TRACE("(%p)->()\n",This); return IUnknown_Release(This->unk.punkControl); } static HRESULT WINAPI ISeekingPassThru_fnInit(ISeekingPassThru* iface,BOOL bRendering,IPin* pPin) { CSeekingPassThru_THIS(iface,seekpass); FIXME("(%p)->(%d,%p) not tested!\n",This,bRendering,pPin); if ( pPin == NULL ) return E_POINTER; /* Why is 'bRendering' given as an argument?? */ EnterCriticalSection( &This->cs ); if ( This->passthru.pPin != NULL ) IPin_Release( This->passthru.pPin ); This->passthru.pPin = pPin; IPin_AddRef( pPin ); LeaveCriticalSection( &This->cs ); return NOERROR; } static ICOM_VTABLE(ISeekingPassThru) iseekingpassthru = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE /* IUnknown fields */ ISeekingPassThru_fnQueryInterface, ISeekingPassThru_fnAddRef, ISeekingPassThru_fnRelease, /* ISeekingPassThru fields */ ISeekingPassThru_fnInit, }; static HRESULT CSeekingPassThru_InitISeekingPassThru(CSeekingPassThru* This) { TRACE("(%p)\n",This); ICOM_VTBL(&This->seekpass) = &iseekingpassthru; This->passthru.punk = This->unk.punkControl; This->passthru.pPin = NULL; InitializeCriticalSection( &This->cs ); return NOERROR; } static void CSeekingPassThru_UninitISeekingPassThru(CSeekingPassThru* This) { TRACE("(%p)\n",This); if ( This->passthru.pPin != NULL ) { IPin_Release( This->passthru.pPin ); This->passthru.pPin = NULL; } DeleteCriticalSection( &This->cs ); } /*************************************************************************** * * new/delete for CLSID_SeekingPassThru. * */ /* can I use offsetof safely? - FIXME? */ static QUARTZ_IFEntry IFEntries[] = { { &IID_ISeekingPassThru, offsetof(CSeekingPassThru,seekpass)-offsetof(CSeekingPassThru,unk) }, { &IID_IMediaPosition, offsetof(CSeekingPassThru,passthru.mpos)-offsetof(CSeekingPassThru,unk) }, { &IID_IMediaSeeking, offsetof(CSeekingPassThru,passthru.mseek)-offsetof(CSeekingPassThru,unk) }, }; static void QUARTZ_DestroySeekingPassThru(IUnknown* punk) { CSeekingPassThru_THIS(punk,unk); TRACE("(%p)\n",This); CPassThruImpl_UninitIMediaSeeking( &This->passthru ); CPassThruImpl_UninitIMediaPosition( &This->passthru ); CSeekingPassThru_UninitISeekingPassThru(This); } HRESULT QUARTZ_CreateSeekingPassThru(IUnknown* punkOuter,void** ppobj) { HRESULT hr; CSeekingPassThru* This; TRACE("(%p,%p)\n",punkOuter,ppobj); hr = QUARTZ_CreateSeekingPassThruInternal(punkOuter,&This,FALSE,NULL); if ( hr != S_OK ) return hr; ppobj = (void*)(&This->unk); return NOERROR; } HRESULT QUARTZ_CreateSeekingPassThruInternal(IUnknown* punkOuter,CSeekingPassThru** ppobj,BOOL bRendering,IPin* pPin) { CSeekingPassThru* This; HRESULT hr; TRACE("(%p,%p,%d,%p)\n",punkOuter,ppobj,(int)bRendering,pPin); This = (CSeekingPassThru*)QUARTZ_AllocObj( sizeof(CSeekingPassThru) ); if ( This == NULL ) return E_OUTOFMEMORY; QUARTZ_IUnkInit( &This->unk, punkOuter ); hr = CSeekingPassThru_InitISeekingPassThru(This); if ( SUCCEEDED(hr) ) { hr = CPassThruImpl_InitIMediaPosition( &This->passthru ); if ( SUCCEEDED(hr) ) { hr = CPassThruImpl_InitIMediaSeeking( &This->passthru ); if ( FAILED(hr) ) { CPassThruImpl_UninitIMediaPosition( &This->passthru ); } } else { CSeekingPassThru_UninitISeekingPassThru(This); } } if ( FAILED(hr) ) { QUARTZ_FreeObj( This ); return hr; } This->unk.pEntries = IFEntries; This->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]); This->unk.pOnFinalRelease = QUARTZ_DestroySeekingPassThru; *ppobj = This; if ( pPin != NULL ) { hr = ISeekingPassThru_Init((ISeekingPassThru*)(&This->seekpass),bRendering,pPin); if ( FAILED(hr) ) { IUnknown_Release(This->unk.punkControl); return hr; } } return S_OK; } /*************************************************************************** * * CPassThruImpl Helper methods. * */ static HRESULT CPassThruImpl_GetConnected( CPassThruImpl* pImpl, IPin** ppPin ) { return IPin_ConnectedTo( pImpl->pPin, ppPin ); } HRESULT CPassThruImpl_QueryPosPass( CPassThruImpl* pImpl, IMediaPosition** ppPosition ) { IPin* pPin; HRESULT hr; hr = CPassThruImpl_GetConnected( pImpl, &pPin ); if ( FAILED(hr) ) return hr; hr = IPin_QueryInterface(pPin,&IID_IMediaPosition,(void**)ppPosition); IPin_Release(pPin); return hr; } HRESULT CPassThruImpl_QuerySeekPass( CPassThruImpl* pImpl, IMediaSeeking** ppSeeking ) { IPin* pPin; HRESULT hr; hr = CPassThruImpl_GetConnected( pImpl, &pPin ); if ( FAILED(hr) ) return hr; hr = IPin_QueryInterface(pPin,&IID_IMediaSeeking,(void**)ppSeeking); IPin_Release(pPin); return hr; } /*************************************************************************** * * An implementation for CPassThruImpl::IMediaPosition. * */ #define QUERYPOSPASS \ IMediaPosition* pPos = NULL; \ HRESULT hr; \ hr = CPassThruImpl_QueryPosPass( This, &pPos ); \ if ( FAILED(hr) ) return hr; static HRESULT WINAPI IMediaPosition_fnQueryInterface(IMediaPosition* iface,REFIID riid,void** ppobj) { CPassThruImpl_THIS(iface,mpos); TRACE("(%p)->()\n",This); return IUnknown_QueryInterface(This->punk,riid,ppobj); } static ULONG WINAPI IMediaPosition_fnAddRef(IMediaPosition* iface) { CPassThruImpl_THIS(iface,mpos); TRACE("(%p)->()\n",This); return IUnknown_AddRef(This->punk); } static ULONG WINAPI IMediaPosition_fnRelease(IMediaPosition* iface) { CPassThruImpl_THIS(iface,mpos); TRACE("(%p)->()\n",This); return IUnknown_Release(This->punk); } static HRESULT WINAPI IMediaPosition_fnGetTypeInfoCount(IMediaPosition* iface,UINT* pcTypeInfo) { CPassThruImpl_THIS(iface,mpos); FIXME("(%p)->() stub!\n",This); return E_NOTIMPL; } static HRESULT WINAPI IMediaPosition_fnGetTypeInfo(IMediaPosition* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj) { CPassThruImpl_THIS(iface,mpos); FIXME("(%p)->() stub!\n",This); return E_NOTIMPL; } static HRESULT WINAPI IMediaPosition_fnGetIDsOfNames(IMediaPosition* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId) { CPassThruImpl_THIS(iface,mpos); FIXME("(%p)->() stub!\n",This); return E_NOTIMPL; } static HRESULT WINAPI IMediaPosition_fnInvoke(IMediaPosition* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr) { CPassThruImpl_THIS(iface,mpos); FIXME("(%p)->() stub!\n",This); return E_NOTIMPL; } static HRESULT WINAPI IMediaPosition_fnget_Duration(IMediaPosition* iface,REFTIME* prefTime) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_get_Duration(pPos,prefTime); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnput_CurrentPosition(IMediaPosition* iface,REFTIME refTime) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_put_CurrentPosition(pPos,refTime); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnget_CurrentPosition(IMediaPosition* iface,REFTIME* prefTime) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_get_CurrentPosition(pPos,prefTime); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnget_StopTime(IMediaPosition* iface,REFTIME* prefTime) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_get_StopTime(pPos,prefTime); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnput_StopTime(IMediaPosition* iface,REFTIME refTime) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_put_StopTime(pPos,refTime); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnget_PrerollTime(IMediaPosition* iface,REFTIME* prefTime) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_get_PrerollTime(pPos,prefTime); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnput_PrerollTime(IMediaPosition* iface,REFTIME refTime) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_put_PrerollTime(pPos,refTime); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnput_Rate(IMediaPosition* iface,double dblRate) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_put_Rate(pPos,dblRate); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnget_Rate(IMediaPosition* iface,double* pdblRate) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_get_Rate(pPos,pdblRate); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnCanSeekForward(IMediaPosition* iface,LONG* pCanSeek) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_CanSeekForward(pPos,pCanSeek); IMediaPosition_Release(pPos); return hr; } static HRESULT WINAPI IMediaPosition_fnCanSeekBackward(IMediaPosition* iface,LONG* pCanSeek) { CPassThruImpl_THIS(iface,mpos); QUERYPOSPASS TRACE("(%p)->()\n",This); hr = IMediaPosition_CanSeekBackward(pPos,pCanSeek); IMediaPosition_Release(pPos); return hr; } static ICOM_VTABLE(IMediaPosition) impos = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE /* IUnknown fields */ IMediaPosition_fnQueryInterface, IMediaPosition_fnAddRef, IMediaPosition_fnRelease, /* IDispatch fields */ IMediaPosition_fnGetTypeInfoCount, IMediaPosition_fnGetTypeInfo, IMediaPosition_fnGetIDsOfNames, IMediaPosition_fnInvoke, /* IMediaPosition fields */ IMediaPosition_fnget_Duration, IMediaPosition_fnput_CurrentPosition, IMediaPosition_fnget_CurrentPosition, IMediaPosition_fnget_StopTime, IMediaPosition_fnput_StopTime, IMediaPosition_fnget_PrerollTime, IMediaPosition_fnput_PrerollTime, IMediaPosition_fnput_Rate, IMediaPosition_fnget_Rate, IMediaPosition_fnCanSeekForward, IMediaPosition_fnCanSeekBackward, }; HRESULT CPassThruImpl_InitIMediaPosition( CPassThruImpl* pImpl ) { TRACE("(%p)\n",pImpl); ICOM_VTBL(&pImpl->mpos) = &impos; return NOERROR; } void CPassThruImpl_UninitIMediaPosition( CPassThruImpl* pImpl ) { TRACE("(%p)\n",pImpl); } #undef QUERYPOSPASS /*************************************************************************** * * An implementation for CPassThruImpl::IMediaSeeking. * */ #define QUERYSEEKPASS \ IMediaSeeking* pSeek = NULL; \ HRESULT hr; \ hr = CPassThruImpl_QuerySeekPass( This, &pSeek ); \ if ( FAILED(hr) ) return hr; static HRESULT WINAPI IMediaSeeking_fnQueryInterface(IMediaSeeking* iface,REFIID riid,void** ppobj) { CPassThruImpl_THIS(iface,mseek); TRACE("(%p)->()\n",This); return IUnknown_QueryInterface(This->punk,riid,ppobj); } static ULONG WINAPI IMediaSeeking_fnAddRef(IMediaSeeking* iface) { CPassThruImpl_THIS(iface,mseek); TRACE("(%p)->()\n",This); return IUnknown_AddRef(This->punk); } static ULONG WINAPI IMediaSeeking_fnRelease(IMediaSeeking* iface) { CPassThruImpl_THIS(iface,mseek); TRACE("(%p)->()\n",This); return IUnknown_Release(This->punk); } static HRESULT WINAPI IMediaSeeking_fnGetCapabilities(IMediaSeeking* iface,DWORD* pdwCaps) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_GetCapabilities(pSeek,pdwCaps); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnCheckCapabilities(IMediaSeeking* iface,DWORD* pdwCaps) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_CheckCapabilities(pSeek,pdwCaps); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnIsFormatSupported(IMediaSeeking* iface,const GUID* pidFormat) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_IsFormatSupported(pSeek,pidFormat); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnQueryPreferredFormat(IMediaSeeking* iface,GUID* pidFormat) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_QueryPreferredFormat(pSeek,pidFormat); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnGetTimeFormat(IMediaSeeking* iface,GUID* pidFormat) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_GetTimeFormat(pSeek,pidFormat); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnIsUsingTimeFormat(IMediaSeeking* iface,const GUID* pidFormat) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_IsUsingTimeFormat(pSeek,pidFormat); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnSetTimeFormat(IMediaSeeking* iface,const GUID* pidFormat) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_SetTimeFormat(pSeek,pidFormat); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnGetDuration(IMediaSeeking* iface,LONGLONG* pllDuration) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_GetDuration(pSeek,pllDuration); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnGetStopPosition(IMediaSeeking* iface,LONGLONG* pllPos) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_GetStopPosition(pSeek,pllPos); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnGetCurrentPosition(IMediaSeeking* iface,LONGLONG* pllPos) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_GetCurrentPosition(pSeek,pllPos); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnConvertTimeFormat(IMediaSeeking* iface,LONGLONG* pllOut,const GUID* pidFmtOut,LONGLONG llIn,const GUID* pidFmtIn) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_ConvertTimeFormat(pSeek,pllOut,pidFmtOut,llIn,pidFmtIn); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnSetPositions(IMediaSeeking* iface,LONGLONG* pllCur,DWORD dwCurFlags,LONGLONG* pllStop,DWORD dwStopFlags) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_SetPositions(pSeek,pllCur,dwCurFlags,pllStop,dwStopFlags); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnGetPositions(IMediaSeeking* iface,LONGLONG* pllCur,LONGLONG* pllStop) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_GetPositions(pSeek,pllCur,pllStop); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnGetAvailable(IMediaSeeking* iface,LONGLONG* pllFirst,LONGLONG* pllLast) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_GetAvailable(pSeek,pllFirst,pllLast); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnSetRate(IMediaSeeking* iface,double dblRate) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_SetRate(pSeek,dblRate); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnGetRate(IMediaSeeking* iface,double* pdblRate) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_GetRate(pSeek,pdblRate); IMediaSeeking_Release(pSeek); return hr; } static HRESULT WINAPI IMediaSeeking_fnGetPreroll(IMediaSeeking* iface,LONGLONG* pllPreroll) { CPassThruImpl_THIS(iface,mseek); QUERYSEEKPASS TRACE("(%p)->()\n",This); hr = IMediaSeeking_GetPreroll(pSeek,pllPreroll); IMediaSeeking_Release(pSeek); return hr; } static ICOM_VTABLE(IMediaSeeking) imseek = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE /* IUnknown fields */ IMediaSeeking_fnQueryInterface, IMediaSeeking_fnAddRef, IMediaSeeking_fnRelease, /* IMediaSeeking fields */ IMediaSeeking_fnGetCapabilities, IMediaSeeking_fnCheckCapabilities, IMediaSeeking_fnIsFormatSupported, IMediaSeeking_fnQueryPreferredFormat, IMediaSeeking_fnGetTimeFormat, IMediaSeeking_fnIsUsingTimeFormat, IMediaSeeking_fnSetTimeFormat, IMediaSeeking_fnGetDuration, IMediaSeeking_fnGetStopPosition, IMediaSeeking_fnGetCurrentPosition, IMediaSeeking_fnConvertTimeFormat, IMediaSeeking_fnSetPositions, IMediaSeeking_fnGetPositions, IMediaSeeking_fnGetAvailable, IMediaSeeking_fnSetRate, IMediaSeeking_fnGetRate, IMediaSeeking_fnGetPreroll, }; HRESULT CPassThruImpl_InitIMediaSeeking( CPassThruImpl* pImpl ) { TRACE("(%p)\n",pImpl); ICOM_VTBL(&pImpl->mseek) = &imseek; return NOERROR; } void CPassThruImpl_UninitIMediaSeeking( CPassThruImpl* pImpl ) { TRACE("(%p)\n",pImpl); } #undef QUERYSEEKPASS