2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy
4 * FILE: dll/directx/ksproxy/clockforward.cpp
5 * PURPOSE: IKsClockForwarder interface
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
11 const GUID IID_IKsClockForwarder
= {0x877e4352, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
13 DWORD WINAPI
CKsClockForwarder_ThreadStartup(LPVOID lpParameter
);
15 class CKsClockForwarder
: public IDistributorNotify
,
19 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
21 STDMETHODIMP_(ULONG
) AddRef()
23 InterlockedIncrement(&m_Ref
);
26 STDMETHODIMP_(ULONG
) Release()
28 InterlockedDecrement(&m_Ref
);
38 // IDistributorNotify interface
39 HRESULT STDMETHODCALLTYPE
Stop();
40 HRESULT STDMETHODCALLTYPE
Pause();
41 HRESULT STDMETHODCALLTYPE
Run(REFERENCE_TIME tStart
);
42 HRESULT STDMETHODCALLTYPE
SetSyncSource(IReferenceClock
*pClock
);
43 HRESULT STDMETHODCALLTYPE
NotifyGraphChange();
45 // IKsObject interface
46 HANDLE STDMETHODCALLTYPE
KsGetObjectHandle();
48 CKsClockForwarder(HANDLE handle
);
49 virtual ~CKsClockForwarder(){};
50 HRESULT STDMETHODCALLTYPE
SetClockState(KSSTATE State
);
54 IReferenceClock
* m_Clock
;
61 REFERENCE_TIME m_Time
;
63 friend DWORD WINAPI
CKsClockForwarder_ThreadStartup(LPVOID lpParameter
);
66 CKsClockForwarder::CKsClockForwarder(
67 HANDLE handle
) : m_Ref(0),
72 m_ThreadStarted(FALSE
),
75 m_State(KSSTATE_STOP
),
82 CKsClockForwarder::QueryInterface(
86 if (IsEqualGUID(refiid
, IID_IUnknown
))
88 *Output
= PVOID(this);
89 reinterpret_cast<IUnknown
*>(*Output
)->AddRef();
92 if (IsEqualGUID(refiid
, IID_IKsObject
) ||
93 IsEqualGUID(refiid
, IID_IKsClockForwarder
))
95 *Output
= (IKsObject
*)(this);
96 reinterpret_cast<IKsObject
*>(*Output
)->AddRef();
100 if (IsEqualGUID(refiid
, IID_IDistributorNotify
))
102 *Output
= (IDistributorNotify
*)(this);
103 reinterpret_cast<IDistributorNotify
*>(*Output
)->AddRef();
107 return E_NOINTERFACE
;
110 //-------------------------------------------------------------------
111 // IDistributorNotify interface
117 CKsClockForwarder::Stop()
121 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
);
122 OutputDebugStringW(Buffer
);
128 // signal pending stop
129 m_PendingStop
= true;
137 // wait untill the thread has finished
138 WaitForSingleObject(m_hThread
, INFINITE
);
140 // close thread handle
141 CloseHandle(m_hThread
);
150 CloseHandle(m_hEvent
);
154 m_PendingStop
= false;
156 SetClockState(KSSTATE_STOP
);
162 CKsClockForwarder::Pause()
165 OutputDebugString("CKsClockForwarder::Pause\n");
170 m_hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
172 return MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, GetLastError());
175 if (m_State
<= KSSTATE_PAUSE
)
177 if (m_State
== KSSTATE_STOP
)
178 SetClockState(KSSTATE_ACQUIRE
);
180 if (m_State
== KSSTATE_ACQUIRE
)
181 SetClockState(KSSTATE_PAUSE
);
187 SetClockState(KSSTATE_PAUSE
);
193 m_hThread
= CreateThread(NULL
, 0, CKsClockForwarder_ThreadStartup
, (LPVOID
)this, 0, NULL
);
195 return MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, GetLastError());
203 CKsClockForwarder::Run(
204 REFERENCE_TIME tStart
)
207 OutputDebugString("CKsClockForwarder::Run\n");
212 if (!m_hEvent
|| !m_hThread
)
215 HRESULT hr
= Pause();
216 m_ForceStart
= FALSE
;
224 SetClockState(KSSTATE_RUN
);
232 CKsClockForwarder::SetSyncSource(
233 IReferenceClock
*pClock
)
236 OutputDebugString("CKsClockForwarder::SetSyncSource\n");
252 CKsClockForwarder::NotifyGraphChange()
255 OutputDebugString("CKsClockForwarder::NotifyGraphChange\n");
261 //-------------------------------------------------------------------
262 // IKsObject interface
267 CKsClockForwarder::KsGetObjectHandle()
272 //-------------------------------------------------------------------
275 CKsClockForwarder::SetClockState(KSSTATE State
)
280 Property
.Set
= KSPROPSETID_Clock
;
281 Property
.Id
= KSPROPERTY_CLOCK_STATE
;
282 Property
.Flags
= KSPROPERTY_TYPE_SET
;
284 HRESULT hr
= KsSynchronousDeviceControl(m_Handle
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), &State
, sizeof(KSSTATE
), &BytesReturned
);
290 swprintf(Buffer
, L
"CKsClockForwarder::SetClockState m_State %u State %u hr %lx\n", m_State
, State
, hr
);
291 OutputDebugStringW(Buffer
);
299 CKsClockForwarder_ThreadStartup(LPVOID lpParameter
)
304 CKsClockForwarder
* Fwd
= (CKsClockForwarder
*)lpParameter
;
306 Fwd
->m_ThreadStarted
= TRUE
;
310 if (Fwd
->m_PendingStop
)
313 if (Fwd
->m_State
!= KSSTATE_RUN
)
314 WaitForSingleObject(Fwd
->m_hEvent
, INFINITE
);
317 Property
.Set
= KSPROPSETID_Clock
;
318 Property
.Id
= KSPROPERTY_CLOCK_TIME
;
319 Property
.Flags
= KSPROPERTY_TYPE_SET
;
321 Fwd
->m_Clock
->GetTime(&Time
);
324 KsSynchronousDeviceControl(Fwd
->m_Handle
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), &Time
, sizeof(REFERENCE_TIME
), &BytesReturned
);
328 Fwd
->m_ThreadStarted
= FALSE
;
334 CKsClockForwarder_Constructor(
335 IUnknown
* pUnkOuter
,
343 OutputDebugStringW(L
"CKsClockForwarder_Constructor\n");
346 // open default clock
347 hr
= KsOpenDefaultDevice(KSCATEGORY_CLOCK
, GENERIC_READ
| GENERIC_WRITE
, &handle
);
352 OutputDebugString("CKsClockForwarder_Constructor failed to open device\n");
357 CKsClockForwarder
* clock
= new CKsClockForwarder(handle
);
363 return E_OUTOFMEMORY
;
366 if (FAILED(clock
->QueryInterface(riid
, ppv
)))
370 return E_NOINTERFACE
;