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)
12 const GUID KSCATEGORY_CLOCK
= {0x53172480, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
15 const GUID IID_IKsClockForwarder
= {0x877e4352, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
17 DWORD WINAPI
CKsClockForwarder_ThreadStartup(LPVOID lpParameter
);
19 class CKsClockForwarder
: public IDistributorNotify
,
23 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
25 STDMETHODIMP_(ULONG
) AddRef()
27 InterlockedIncrement(&m_Ref
);
30 STDMETHODIMP_(ULONG
) Release()
32 InterlockedDecrement(&m_Ref
);
42 // IDistributorNotify interface
43 HRESULT STDMETHODCALLTYPE
Stop();
44 HRESULT STDMETHODCALLTYPE
Pause();
45 HRESULT STDMETHODCALLTYPE
Run(REFERENCE_TIME tStart
);
46 HRESULT STDMETHODCALLTYPE
SetSyncSource(IReferenceClock
*pClock
);
47 HRESULT STDMETHODCALLTYPE
NotifyGraphChange();
49 // IKsObject interface
50 HANDLE STDMETHODCALLTYPE
KsGetObjectHandle();
52 CKsClockForwarder(HANDLE handle
);
53 virtual ~CKsClockForwarder(){};
54 HRESULT STDMETHODCALLTYPE
SetClockState(KSSTATE State
);
58 IReferenceClock
* m_Clock
;
65 REFERENCE_TIME m_Time
;
67 friend DWORD WINAPI
CKsClockForwarder_ThreadStartup(LPVOID lpParameter
);
70 CKsClockForwarder::CKsClockForwarder(
71 HANDLE handle
) : m_Ref(0),
76 m_ThreadStarted(FALSE
),
79 m_State(KSSTATE_STOP
),
86 CKsClockForwarder::QueryInterface(
90 if (IsEqualGUID(refiid
, IID_IUnknown
))
92 *Output
= PVOID(this);
93 reinterpret_cast<IUnknown
*>(*Output
)->AddRef();
96 if (IsEqualGUID(refiid
, IID_IKsObject
) ||
97 IsEqualGUID(refiid
, IID_IKsClockForwarder
))
99 *Output
= (IKsObject
*)(this);
100 reinterpret_cast<IKsObject
*>(*Output
)->AddRef();
104 if (IsEqualGUID(refiid
, IID_IDistributorNotify
))
106 *Output
= (IDistributorNotify
*)(this);
107 reinterpret_cast<IDistributorNotify
*>(*Output
)->AddRef();
111 return E_NOINTERFACE
;
114 //-------------------------------------------------------------------
115 // IDistributorNotify interface
121 CKsClockForwarder::Stop()
125 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
);
126 OutputDebugStringW(Buffer
);
132 // signal pending stop
133 m_PendingStop
= true;
141 // wait untill the thread has finished
142 WaitForSingleObject(m_hThread
, INFINITE
);
144 // close thread handle
145 CloseHandle(m_hThread
);
154 CloseHandle(m_hEvent
);
158 m_PendingStop
= false;
160 SetClockState(KSSTATE_STOP
);
166 CKsClockForwarder::Pause()
169 OutputDebugString("CKsClockForwarder::Pause\n");
174 m_hEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
176 return MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, GetLastError());
179 if (m_State
<= KSSTATE_PAUSE
)
181 if (m_State
== KSSTATE_STOP
)
182 SetClockState(KSSTATE_ACQUIRE
);
184 if (m_State
== KSSTATE_ACQUIRE
)
185 SetClockState(KSSTATE_PAUSE
);
191 SetClockState(KSSTATE_PAUSE
);
197 m_hThread
= CreateThread(NULL
, 0, CKsClockForwarder_ThreadStartup
, (LPVOID
)this, 0, NULL
);
199 return MAKE_HRESULT(SEVERITY_ERROR
, FACILITY_WIN32
, GetLastError());
207 CKsClockForwarder::Run(
208 REFERENCE_TIME tStart
)
211 OutputDebugString("CKsClockForwarder::Run\n");
216 if (!m_hEvent
|| !m_hThread
)
219 HRESULT hr
= Pause();
220 m_ForceStart
= FALSE
;
228 SetClockState(KSSTATE_RUN
);
236 CKsClockForwarder::SetSyncSource(
237 IReferenceClock
*pClock
)
240 OutputDebugString("CKsClockForwarder::SetSyncSource\n");
256 CKsClockForwarder::NotifyGraphChange()
259 OutputDebugString("CKsClockForwarder::NotifyGraphChange\n");
265 //-------------------------------------------------------------------
266 // IKsObject interface
271 CKsClockForwarder::KsGetObjectHandle()
276 //-------------------------------------------------------------------
279 CKsClockForwarder::SetClockState(KSSTATE State
)
284 Property
.Set
= KSPROPSETID_Clock
;
285 Property
.Id
= KSPROPERTY_CLOCK_STATE
;
286 Property
.Flags
= KSPROPERTY_TYPE_SET
;
288 HRESULT hr
= KsSynchronousDeviceControl(m_Handle
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), &State
, sizeof(KSSTATE
), &BytesReturned
);
294 swprintf(Buffer
, L
"CKsClockForwarder::SetClockState m_State %u State %u hr %lx\n", m_State
, State
, hr
);
295 OutputDebugStringW(Buffer
);
303 CKsClockForwarder_ThreadStartup(LPVOID lpParameter
)
308 CKsClockForwarder
* Fwd
= (CKsClockForwarder
*)lpParameter
;
310 Fwd
->m_ThreadStarted
= TRUE
;
314 if (Fwd
->m_PendingStop
)
317 if (Fwd
->m_State
!= KSSTATE_RUN
)
318 WaitForSingleObject(Fwd
->m_hEvent
, INFINITE
);
321 Property
.Set
= KSPROPSETID_Clock
;
322 Property
.Id
= KSPROPERTY_CLOCK_TIME
;
323 Property
.Flags
= KSPROPERTY_TYPE_SET
;
325 Fwd
->m_Clock
->GetTime(&Time
);
328 KsSynchronousDeviceControl(Fwd
->m_Handle
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), &Time
, sizeof(REFERENCE_TIME
), &BytesReturned
);
332 Fwd
->m_ThreadStarted
= FALSE
;
338 CKsClockForwarder_Constructor(
339 IUnknown
* pUnkOuter
,
347 OutputDebugStringW(L
"CKsClockForwarder_Constructor\n");
350 // open default clock
351 hr
= KsOpenDefaultDevice(KSCATEGORY_CLOCK
, GENERIC_READ
| GENERIC_WRITE
, &handle
);
356 OutputDebugString("CKsClockForwarder_Constructor failed to open device\n");
361 CKsClockForwarder
* clock
= new CKsClockForwarder(handle
);
367 return E_OUTOFMEMORY
;
370 if (FAILED(clock
->QueryInterface(riid
, ppv
)))
374 return E_NOINTERFACE
;