home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / refclock.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-11  |  7.3 KB  |  170 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //  REFCLOCK.H
  12. //  Implements IReferenceClock Interface
  13.  
  14. #ifndef __BASEREFCLOCK__
  15. #define __BASEREFCLOCK__
  16.  
  17. #include <Schedule.h>
  18.  
  19. const UINT RESOLUTION = 1;                      /* High resolution timer */
  20. const INT ADVISE_CACHE = 4;                     /* Default cache size */
  21. const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF;   /* Maximum LONGLONG value */
  22.  
  23. inline LONGLONG ConvertToMilliseconds(const REFERENCE_TIME& RT)
  24. {
  25.     /* This converts an arbitrary value representing a reference time
  26.        into a MILLISECONDS value for use in subsequent system calls */
  27.  
  28.     return (RT / (UNITS / MILLISECONDS));
  29. }
  30.  
  31. /* This class hierarchy will support an IReferenceClock interface so
  32.    that an audio card (or other externally driven clock) can update the
  33.    system wide clock that everyone uses.
  34.  
  35.    The interface will be pretty thin with probably just one update method
  36.    This interface has not yet been defined.
  37.  */
  38.  
  39. /* This abstract base class implements the IReferenceClock
  40.  * interface.  Classes that actually provide clock signals (from
  41.  * whatever source) have to be derived from this class.
  42.  *
  43.  * The abstract class provides implementations for:
  44.  *     CUnknown support
  45.  *      locking support (CCritSec)
  46.  *    client advise code (creates a thread)
  47.  *
  48.  * Question: what can we do about quality?  Change the timer
  49.  * resolution to lower the system load?  Up the priority of the
  50.  * timer thread to force more responsive signals?
  51.  *
  52.  * During class construction we create a worker thread that is destroyed during
  53.  * destuction.  This thread executes a series of WaitForSingleObject calls,
  54.  * waking up when a command is given to the thread or the next wake up point
  55.  * is reached.  The wakeup points are determined by clients making Advise
  56.  * calls.
  57.  *
  58.  * Each advise call defines a point in time when they wish to be notified.  A
  59.  * periodic advise is a series of these such events.  We maintain a list of
  60.  * advise links and calculate when the nearest event notification is due for.
  61.  * We then call WaitForSingleObject with a timeout equal to this time.  The
  62.  * handle we wait on is used by the class to signal that something has changed
  63.  * and that we must reschedule the next event.  This typically happens when
  64.  * someone comes in and asks for an advise link while we are waiting for an
  65.  * event to timeout.
  66.  *
  67.  * While we are modifying the list of advise requests we
  68.  * are protected from interference through a critical section.  Clients are NOT
  69.  * advised through callbacks.  One shot clients have an event set, while
  70.  * periodic clients have a semaphore released for each event notification.  A
  71.  * semaphore allows a client to be kept up to date with the number of events
  72.  * actually triggered and be assured that they can't miss multiple events being
  73.  * set.
  74.  *
  75.  * Keeping track of advises are taken care of by the CAMSchedule class, from 
  76.  * which we inherit.
  77.  */
  78.  
  79. class CBaseReferenceClock 
  80. : public CUnknown, public IReferenceClock, public CAMSchedule, public CCritSec
  81. {
  82. protected:
  83.     virtual ~CBaseReferenceClock();     // Don't let me be created on the stack!
  84. public:
  85.     CBaseReferenceClock(TCHAR *pName,LPUNKNOWN pUnk,HRESULT *phr);
  86.  
  87.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void ** ppv);
  88.  
  89.     DECLARE_IUNKNOWN
  90.  
  91.     /* IReferenceClock methods */
  92.     // Derived classes must implement GetPrivateTime().  All our GetTime
  93.     // does is call GetPrivateTime and then check so that time does not
  94.     // go backwards.  A return code of S_FALSE implies that the internal
  95.     // clock has gone backwards and GetTime time has halted until internal
  96.     // time has caught up. (Don't know if this will be much use to folk, 
  97.     // but it seems silly not to use the return code for something useful.)
  98.     STDMETHODIMP GetTime(REFERENCE_TIME *pTime);
  99.     // When this is called, it sets m_rtLastGotTime to the time it returns.
  100.  
  101.     /* Provide standard mechanisms for scheduling events */
  102.  
  103.     /* Ask for an async notification that a time has elapsed */
  104.     STDMETHODIMP AdviseTime(
  105.         REFERENCE_TIME baseTime,        // base reference time
  106.         REFERENCE_TIME streamTime,      // stream offset time
  107.         HEVENT hEvent,                  // advise via this event
  108.         DWORD *pdwAdviseCookie          // where your cookie goes
  109.     );
  110.  
  111.     /* Ask for an asynchronous periodic notification that a time has elapsed */
  112.     STDMETHODIMP AdvisePeriodic(
  113.         REFERENCE_TIME StartTime,       // starting at this time
  114.         REFERENCE_TIME PeriodTime,      // time between notifications
  115.         HSEMAPHORE hSemaphore,          // advise via a semaphore
  116.         DWORD *pdwAdviseCookie          // where your cookie goes
  117.     );
  118.  
  119.     /* Cancel a request for notification(s) - if the notification was
  120.      * a one shot timer then this function doesn't need to be called
  121.      * as the advise is automatically cancelled, however it does no
  122.      * harm to explicitly cancel a one-shot advise.  It is REQUIRED that
  123.      * clients call Unadvise to clear a Periodic advise setting.
  124.      */
  125.  
  126.     STDMETHODIMP Unadvise(DWORD dwAdviseCookie);
  127.  
  128.     /* Methods for the benefit of derived classes or outer objects */
  129.  
  130.     // We override CAMScheduse's version in order to trigget the thread if needed
  131.     DWORD AddAdvisePacket( const REFERENCE_TIME & time1, const REFERENCE_TIME & time2, HANDLE h, BOOL periodic );
  132.     // GetPrivateTime() is the REAL clock.  GetTime is just a cover for
  133.     // it.  Derived classes will probably override this method but not 
  134.     // GetTime() itself.
  135.     // The important point about GetPrivateTime() is it's allowed to go
  136.     // backwards.  Our GetTime() will keep returning the LastGotTime 
  137.     // until GetPrivateTime() catches up.
  138.     virtual REFERENCE_TIME GetPrivateTime();
  139.  
  140.     /* Provide a method for correcting drift */
  141.     STDMETHODIMP SetTimeDelta( const REFERENCE_TIME& TimeDelta );
  142.  
  143. private:
  144.     REFERENCE_TIME m_rtPrivateTime;     // Current best estimate of time
  145.     DWORD          m_dwPrevSystemTime;  // Last vaule we got from timeGetTime
  146.     REFERENCE_TIME m_rtLastGotTime;     // Last time returned by GetTime
  147.     REFERENCE_TIME m_rtNextAdvise;      // Time of next advise
  148.     UINT           m_TimerResolution; 
  149.  
  150. #ifdef PERF
  151.     int m_idGetSystemTime;
  152. #endif
  153.  
  154. // Thread stuff
  155. public:
  156.     void TriggerThread()                // Wakes thread up.  Need to do this if
  157.     { m_Event.Set(); }                  // time to next advise needs reevaluating.
  158.  
  159. private:
  160.     BOOL           m_bAbort;            // Flag used for thread shutdown
  161.     CAMEvent       m_Event;             // Signal when its time to check advises
  162.     HANDLE         m_hThread;           // Thread handle
  163.  
  164.     HRESULT AdviseThread();             // Method in which the advise thread runs
  165.     static DWORD __stdcall AdviseThreadFunction(LPVOID); // Function is uses to get there
  166. };
  167.  
  168. #endif 
  169.  
  170.