ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

clockforward.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.