Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenclockforward.cpp
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy 00004 * FILE: dll/directx/ksproxy/clockforward.cpp 00005 * PURPOSE: IKsClockForwarder interface 00006 * 00007 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) 00008 */ 00009 #include "precomp.h" 00010 00011 #ifndef _MSC_VER 00012 const GUID KSCATEGORY_CLOCK = {0x53172480, 0x4791, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00013 #endif 00014 00015 const GUID IID_IKsClockForwarder = {0x877e4352, 0x6fea, 0x11d0, {0xb8, 0x63, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}}; 00016 00017 DWORD WINAPI CKsClockForwarder_ThreadStartup(LPVOID lpParameter); 00018 00019 class CKsClockForwarder : public IDistributorNotify, 00020 public IKsObject 00021 { 00022 public: 00023 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 00024 00025 STDMETHODIMP_(ULONG) AddRef() 00026 { 00027 InterlockedIncrement(&m_Ref); 00028 return m_Ref; 00029 } 00030 STDMETHODIMP_(ULONG) Release() 00031 { 00032 InterlockedDecrement(&m_Ref); 00033 00034 if (!m_Ref) 00035 { 00036 delete this; 00037 return 0; 00038 } 00039 return m_Ref; 00040 } 00041 00042 // IDistributorNotify interface 00043 HRESULT STDMETHODCALLTYPE Stop(); 00044 HRESULT STDMETHODCALLTYPE Pause(); 00045 HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart); 00046 HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock); 00047 HRESULT STDMETHODCALLTYPE NotifyGraphChange(); 00048 00049 // IKsObject interface 00050 HANDLE STDMETHODCALLTYPE KsGetObjectHandle(); 00051 00052 CKsClockForwarder(HANDLE handle); 00053 virtual ~CKsClockForwarder(){}; 00054 HRESULT STDMETHODCALLTYPE SetClockState(KSSTATE State); 00055 protected: 00056 LONG m_Ref; 00057 HANDLE m_Handle; 00058 IReferenceClock * m_Clock; 00059 HANDLE m_hEvent; 00060 HANDLE m_hThread; 00061 BOOL m_ThreadStarted; 00062 BOOL m_PendingStop; 00063 BOOL m_ForceStart; 00064 KSSTATE m_State; 00065 REFERENCE_TIME m_Time; 00066 00067 friend DWORD WINAPI CKsClockForwarder_ThreadStartup(LPVOID lpParameter); 00068 }; 00069 00070 CKsClockForwarder::CKsClockForwarder( 00071 HANDLE handle) : m_Ref(0), 00072 m_Handle(handle), 00073 m_Clock(0), 00074 m_hEvent(NULL), 00075 m_hThread(NULL), 00076 m_ThreadStarted(FALSE), 00077 m_PendingStop(FALSE), 00078 m_ForceStart(FALSE), 00079 m_State(KSSTATE_STOP), 00080 m_Time(0) 00081 { 00082 } 00083 00084 HRESULT 00085 STDMETHODCALLTYPE 00086 CKsClockForwarder::QueryInterface( 00087 IN REFIID refiid, 00088 OUT PVOID* Output) 00089 { 00090 if (IsEqualGUID(refiid, IID_IUnknown)) 00091 { 00092 *Output = PVOID(this); 00093 reinterpret_cast<IUnknown*>(*Output)->AddRef(); 00094 return NOERROR; 00095 } 00096 if (IsEqualGUID(refiid, IID_IKsObject) || 00097 IsEqualGUID(refiid, IID_IKsClockForwarder)) 00098 { 00099 *Output = (IKsObject*)(this); 00100 reinterpret_cast<IKsObject*>(*Output)->AddRef(); 00101 return NOERROR; 00102 } 00103 00104 if (IsEqualGUID(refiid, IID_IDistributorNotify)) 00105 { 00106 *Output = (IDistributorNotify*)(this); 00107 reinterpret_cast<IDistributorNotify*>(*Output)->AddRef(); 00108 return NOERROR; 00109 } 00110 00111 return E_NOINTERFACE; 00112 } 00113 00114 //------------------------------------------------------------------- 00115 // IDistributorNotify interface 00116 // 00117 00118 00119 HRESULT 00120 STDMETHODCALLTYPE 00121 CKsClockForwarder::Stop() 00122 { 00123 #ifdef KSPROXY_TRACE 00124 WCHAR Buffer[200]; 00125 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); 00126 OutputDebugStringW(Buffer); 00127 #endif 00128 00129 m_Time = 0; 00130 if (m_ThreadStarted) 00131 { 00132 // signal pending stop 00133 m_PendingStop = true; 00134 00135 assert(m_hThread); 00136 assert(m_hEvent); 00137 00138 // set stop event 00139 SetEvent(m_hEvent); 00140 00141 // wait untill the thread has finished 00142 WaitForSingleObject(m_hThread, INFINITE); 00143 00144 // close thread handle 00145 CloseHandle(m_hThread); 00146 00147 // zero handle 00148 m_hThread = NULL; 00149 } 00150 00151 if (m_hEvent) 00152 { 00153 // close stop event 00154 CloseHandle(m_hEvent); 00155 m_hEvent = NULL; 00156 } 00157 00158 m_PendingStop = false; 00159 00160 SetClockState(KSSTATE_STOP); 00161 return NOERROR; 00162 } 00163 00164 HRESULT 00165 STDMETHODCALLTYPE 00166 CKsClockForwarder::Pause() 00167 { 00168 #ifdef KSPROXY_TRACE 00169 OutputDebugString("CKsClockForwarder::Pause\n"); 00170 #endif 00171 00172 if (!m_hEvent) 00173 { 00174 m_hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 00175 if (!m_hEvent) 00176 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); 00177 } 00178 00179 if (m_State <= KSSTATE_PAUSE) 00180 { 00181 if (m_State == KSSTATE_STOP) 00182 SetClockState(KSSTATE_ACQUIRE); 00183 00184 if (m_State == KSSTATE_ACQUIRE) 00185 SetClockState(KSSTATE_PAUSE); 00186 } 00187 else 00188 { 00189 if (!m_ForceStart) 00190 { 00191 SetClockState(KSSTATE_PAUSE); 00192 } 00193 } 00194 00195 if (!m_hThread) 00196 { 00197 m_hThread = CreateThread(NULL, 0, CKsClockForwarder_ThreadStartup, (LPVOID)this, 0, NULL); 00198 if (!m_hThread) 00199 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); 00200 } 00201 00202 return NOERROR; 00203 } 00204 00205 HRESULT 00206 STDMETHODCALLTYPE 00207 CKsClockForwarder::Run( 00208 REFERENCE_TIME tStart) 00209 { 00210 #ifdef KSPROXY_TRACE 00211 OutputDebugString("CKsClockForwarder::Run\n"); 00212 #endif 00213 00214 m_Time = tStart; 00215 00216 if (!m_hEvent || !m_hThread) 00217 { 00218 m_ForceStart = TRUE; 00219 HRESULT hr = Pause(); 00220 m_ForceStart = FALSE; 00221 00222 if (FAILED(hr)) 00223 return hr; 00224 } 00225 00226 assert(m_hThread); 00227 00228 SetClockState(KSSTATE_RUN); 00229 SetEvent(m_hEvent); 00230 00231 return NOERROR; 00232 } 00233 00234 HRESULT 00235 STDMETHODCALLTYPE 00236 CKsClockForwarder::SetSyncSource( 00237 IReferenceClock *pClock) 00238 { 00239 #ifdef KSPROXY_TRACE 00240 OutputDebugString("CKsClockForwarder::SetSyncSource\n"); 00241 #endif 00242 00243 if (pClock) 00244 pClock->AddRef(); 00245 00246 if (m_Clock) 00247 m_Clock->Release(); 00248 00249 00250 m_Clock = pClock; 00251 return NOERROR; 00252 } 00253 00254 HRESULT 00255 STDMETHODCALLTYPE 00256 CKsClockForwarder::NotifyGraphChange() 00257 { 00258 #ifdef KSPROXY_TRACE 00259 OutputDebugString("CKsClockForwarder::NotifyGraphChange\n"); 00260 #endif 00261 00262 return NOERROR; 00263 } 00264 00265 //------------------------------------------------------------------- 00266 // IKsObject interface 00267 // 00268 00269 HANDLE 00270 STDMETHODCALLTYPE 00271 CKsClockForwarder::KsGetObjectHandle() 00272 { 00273 return m_Handle; 00274 } 00275 00276 //------------------------------------------------------------------- 00277 HRESULT 00278 STDMETHODCALLTYPE 00279 CKsClockForwarder::SetClockState(KSSTATE State) 00280 { 00281 KSPROPERTY Property; 00282 ULONG BytesReturned; 00283 00284 Property.Set = KSPROPSETID_Clock; 00285 Property.Id = KSPROPERTY_CLOCK_STATE; 00286 Property.Flags = KSPROPERTY_TYPE_SET; 00287 00288 HRESULT hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &BytesReturned); 00289 if (SUCCEEDED(hr)) 00290 m_State = State; 00291 00292 #ifdef KSPROXY_TRACE 00293 WCHAR Buffer[100]; 00294 swprintf(Buffer, L"CKsClockForwarder::SetClockState m_State %u State %u hr %lx\n", m_State, State, hr); 00295 OutputDebugStringW(Buffer); 00296 #endif 00297 00298 return hr; 00299 } 00300 00301 DWORD 00302 WINAPI 00303 CKsClockForwarder_ThreadStartup(LPVOID lpParameter) 00304 { 00305 REFERENCE_TIME Time; 00306 ULONG BytesReturned; 00307 00308 CKsClockForwarder * Fwd = (CKsClockForwarder*)lpParameter; 00309 00310 Fwd->m_ThreadStarted = TRUE; 00311 00312 do 00313 { 00314 if (Fwd->m_PendingStop) 00315 break; 00316 00317 if (Fwd->m_State != KSSTATE_RUN) 00318 WaitForSingleObject(Fwd->m_hEvent, INFINITE); 00319 00320 KSPROPERTY Property; 00321 Property.Set = KSPROPSETID_Clock; 00322 Property.Id = KSPROPERTY_CLOCK_TIME; 00323 Property.Flags = KSPROPERTY_TYPE_SET; 00324 00325 Fwd->m_Clock->GetTime(&Time); 00326 Time -= Fwd->m_Time; 00327 00328 KsSynchronousDeviceControl(Fwd->m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), &Time, sizeof(REFERENCE_TIME), &BytesReturned); 00329 } 00330 while(TRUE); 00331 00332 Fwd->m_ThreadStarted = FALSE; 00333 return NOERROR; 00334 } 00335 00336 HRESULT 00337 WINAPI 00338 CKsClockForwarder_Constructor( 00339 IUnknown * pUnkOuter, 00340 REFIID riid, 00341 LPVOID * ppv) 00342 { 00343 HRESULT hr; 00344 HANDLE handle; 00345 00346 #ifdef KSPROXY_TRACE 00347 OutputDebugStringW(L"CKsClockForwarder_Constructor\n"); 00348 #endif 00349 00350 // open default clock 00351 hr = KsOpenDefaultDevice(KSCATEGORY_CLOCK, GENERIC_READ | GENERIC_WRITE, &handle); 00352 00353 if (hr != NOERROR) 00354 { 00355 #ifdef KSPROXY_TRACE 00356 OutputDebugString("CKsClockForwarder_Constructor failed to open device\n"); 00357 #endif 00358 return hr; 00359 } 00360 00361 CKsClockForwarder * clock = new CKsClockForwarder(handle); 00362 00363 if (!clock) 00364 { 00365 // free clock handle 00366 CloseHandle(handle); 00367 return E_OUTOFMEMORY; 00368 } 00369 00370 if (FAILED(clock->QueryInterface(riid, ppv))) 00371 { 00372 /* not supported */ 00373 delete clock; 00374 return E_NOINTERFACE; 00375 } 00376 00377 return NOERROR; 00378 } Generated on Sun May 27 2012 04:21:50 for ReactOS by
1.7.6.1
|