Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy * FILE: dll/directx/ksproxy/clockforward.cpp * PURPOSE: IKsClockForwarder interface * * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org) */#include "precomp.h"
const GUID IID_IKsClockForwarder = {0x877e4352, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
DWORD WINAPI CKsClockForwarder_ThreadStartup(LPVOID lpParameter);
class CKsClockForwarder : public IDistributorNotify, public IKsObject{public: STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
STDMETHODIMP_(ULONG) AddRef() { InterlockedIncrement(&m_Ref); return m_Ref; } STDMETHODIMP_(ULONG) Release() { InterlockedDecrement(&m_Ref);
if (!m_Ref) { delete this; return 0; } return m_Ref; }
// IDistributorNotify interface HRESULT STDMETHODCALLTYPE Stop(); HRESULT STDMETHODCALLTYPE Pause(); HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart); HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock); HRESULT STDMETHODCALLTYPE NotifyGraphChange();
// IKsObject interface HANDLE STDMETHODCALLTYPE KsGetObjectHandle();
CKsClockForwarder(HANDLE handle); virtual ~CKsClockForwarder(){}; HRESULT STDMETHODCALLTYPE SetClockState(KSSTATE State);protected: LONG m_Ref; HANDLE m_Handle; IReferenceClock * m_Clock; HANDLE m_hEvent; HANDLE m_hThread; BOOL m_ThreadStarted; BOOL m_PendingStop; BOOL m_ForceStart; KSSTATE m_State; REFERENCE_TIME m_Time;
friend DWORD WINAPI CKsClockForwarder_ThreadStartup(LPVOID lpParameter);};
CKsClockForwarder::CKsClockForwarder( HANDLE handle) : m_Ref(0), m_Handle(handle), m_Clock(0), m_hEvent(NULL), m_hThread(NULL), m_ThreadStarted(FALSE), m_PendingStop(FALSE), m_ForceStart(FALSE), m_State(KSSTATE_STOP), m_Time(0){}
HRESULTSTDMETHODCALLTYPECKsClockForwarder::QueryInterface( IN REFIID refiid, OUT PVOID* Output){ if (IsEqualGUID(refiid, IID_IUnknown)) { *Output = PVOID(this); reinterpret_cast<IUnknown*>(*Output)->AddRef(); return NOERROR; } if (IsEqualGUID(refiid, IID_IKsObject) || IsEqualGUID(refiid, IID_IKsClockForwarder)) { *Output = (IKsObject*)(this); reinterpret_cast<IKsObject*>(*Output)->AddRef(); return NOERROR; }
if (IsEqualGUID(refiid, IID_IDistributorNotify)) { *Output = (IDistributorNotify*)(this); reinterpret_cast<IDistributorNotify*>(*Output)->AddRef(); return NOERROR; }
return E_NOINTERFACE;}
//-------------------------------------------------------------------// IDistributorNotify interface//
HRESULTSTDMETHODCALLTYPECKsClockForwarder::Stop(){#ifdef KSPROXY_TRACE WCHAR Buffer[200]; swprintf(Buffer, L"CKsClockForwarder::Stop m_ThreadStarted %u m_PendingStop %u m_hThread %p m_hEvent %p m_Handle %p\n", m_ThreadStarted, m_PendingStop, m_hThread, m_hEvent, m_Handle); OutputDebugStringW(Buffer);#endif
m_Time = 0; if (m_ThreadStarted) { // signal pending stop m_PendingStop = true;
assert(m_hThread); assert(m_hEvent);
// set stop event SetEvent(m_hEvent);
// wait untill the thread has finished WaitForSingleObject(m_hThread, INFINITE);
// close thread handle CloseHandle(m_hThread);
// zero handle m_hThread = NULL; }
if (m_hEvent) { // close stop event CloseHandle(m_hEvent); m_hEvent = NULL; }
m_PendingStop = false;
SetClockState(KSSTATE_STOP); return NOERROR;}
HRESULTSTDMETHODCALLTYPECKsClockForwarder::Pause(){#ifdef KSPROXY_TRACE OutputDebugString("CKsClockForwarder::Pause\n");#endif
if (!m_hEvent) { m_hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if (!m_hEvent) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); }
if (m_State <= KSSTATE_PAUSE) { if (m_State == KSSTATE_STOP) SetClockState(KSSTATE_ACQUIRE);
if (m_State == KSSTATE_ACQUIRE) SetClockState(KSSTATE_PAUSE); } else { if (!m_ForceStart) { SetClockState(KSSTATE_PAUSE); } }
if (!m_hThread) { m_hThread = CreateThread(NULL, 0, CKsClockForwarder_ThreadStartup, (LPVOID)this, 0, NULL); if (!m_hThread) return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); }
return NOERROR;}
HRESULTSTDMETHODCALLTYPECKsClockForwarder::Run( REFERENCE_TIME tStart){#ifdef KSPROXY_TRACE OutputDebugString("CKsClockForwarder::Run\n");#endif
m_Time = tStart;
if (!m_hEvent || !m_hThread) { m_ForceStart = TRUE; HRESULT hr = Pause(); m_ForceStart = FALSE;
if (FAILED(hr)) return hr; }
assert(m_hThread);
SetClockState(KSSTATE_RUN); SetEvent(m_hEvent);
return NOERROR;}
HRESULTSTDMETHODCALLTYPECKsClockForwarder::SetSyncSource( IReferenceClock *pClock){#ifdef KSPROXY_TRACE OutputDebugString("CKsClockForwarder::SetSyncSource\n");#endif
if (pClock) pClock->AddRef();
if (m_Clock) m_Clock->Release();
m_Clock = pClock; return NOERROR;}
HRESULTSTDMETHODCALLTYPECKsClockForwarder::NotifyGraphChange(){#ifdef KSPROXY_TRACE OutputDebugString("CKsClockForwarder::NotifyGraphChange\n");#endif
return NOERROR;}
//-------------------------------------------------------------------// IKsObject interface//
HANDLESTDMETHODCALLTYPECKsClockForwarder::KsGetObjectHandle(){ return m_Handle;}
//-------------------------------------------------------------------HRESULTSTDMETHODCALLTYPECKsClockForwarder::SetClockState(KSSTATE State){ KSPROPERTY Property; ULONG BytesReturned;
Property.Set = KSPROPSETID_Clock; Property.Id = KSPROPERTY_CLOCK_STATE; Property.Flags = KSPROPERTY_TYPE_SET;
HRESULT hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &BytesReturned); if (SUCCEEDED(hr)) m_State = State;
#ifdef KSPROXY_TRACE WCHAR Buffer[100]; swprintf(Buffer, L"CKsClockForwarder::SetClockState m_State %u State %u hr %lx\n", m_State, State, hr); OutputDebugStringW(Buffer);#endif
return hr;}
DWORDWINAPICKsClockForwarder_ThreadStartup(LPVOID lpParameter){ REFERENCE_TIME Time; ULONG BytesReturned;
CKsClockForwarder * Fwd = (CKsClockForwarder*)lpParameter;
Fwd->m_ThreadStarted = TRUE;
do { if (Fwd->m_PendingStop) break;
if (Fwd->m_State != KSSTATE_RUN) WaitForSingleObject(Fwd->m_hEvent, INFINITE);
KSPROPERTY Property; Property.Set = KSPROPSETID_Clock; Property.Id = KSPROPERTY_CLOCK_TIME; Property.Flags = KSPROPERTY_TYPE_SET;
Fwd->m_Clock->GetTime(&Time); Time -= Fwd->m_Time;
KsSynchronousDeviceControl(Fwd->m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), &Time, sizeof(REFERENCE_TIME), &BytesReturned); } while(TRUE);
Fwd->m_ThreadStarted = FALSE; return NOERROR;}
HRESULTWINAPICKsClockForwarder_Constructor( IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv){ HRESULT hr; HANDLE handle;
#ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsClockForwarder_Constructor\n");#endif
// open default clock hr = KsOpenDefaultDevice(KSCATEGORY_CLOCK, GENERIC_READ | GENERIC_WRITE, &handle);
if (hr != NOERROR) {#ifdef KSPROXY_TRACE OutputDebugString("CKsClockForwarder_Constructor failed to open device\n");#endif return hr; }
CKsClockForwarder * clock = new CKsClockForwarder(handle);
if (!clock) { // free clock handle CloseHandle(handle); return E_OUTOFMEMORY; }
if (FAILED(clock->QueryInterface(riid, ppv))) { /* not supported */ delete clock; return E_NOINTERFACE; }
return NOERROR;}