 --  available under LGPL Version 2. The documentation included with
 --  this library is based on the original GStreamer documentation.
 --  
--- | Maintainer  : gtk2hs-devel@lists.sourceforge.net
---   Stability   : alpha
---   Portability : portable (depends on GHC)
+--  |
+--  Maintainer  : gtk2hs-devel@lists.sourceforge.net
+--  Stability   : alpha
+--  Portability : portable (depends on GHC)
+--  
+--  Abstract class of global clocks.
 module Media.Streaming.GStreamer.Core.Clock (
   
+-- * Detail
+  -- | GStreamer uses a global clock to synchronize the plugins in a
+  --   pipeline. Different clock implementations are possible by
+  --   implementing this abstract base class.
+  --   
+  --   The 'Clock' returns a monotonically increasing time with the
+  --   method 'clockGetTime'. Its accuracy and base time depend
+  --   on the specific clock implementation but time is always
+  --   expressed in nanoseconds. Since the baseline of the clock is
+  --   undefined, the clock time returned is not meaningful in itself,
+  --   what matters are the deltas between two clock times. The time
+  --   returned by a clock is called the absolute time.
+  --   
+  --   The pipeline uses the clock to calculate the stream
+  --   time. Usually all renderers synchronize to the global clock
+  --   using the buffer timestamps, the newsegment events and the
+  --   element's base time, see GstPipeline.
+  --   
+  --   A clock implementation can support periodic and single shot
+  --   clock notifications both synchronous and asynchronous.
+  --   
+  --   One first needs to create a 'ClockID' for the periodic or
+  --   single shot notification using 'clockNewSingleShotID' or
+  --   'clockNewPeriodicID'.
+  --   
+  --   To perform a blocking wait for the specific time of the
+  --   'ClockID' use 'clockIDWait'. This calls can be interrupted with
+  --   the 'clockIDUnschedule' call. If the blocking wait is
+  --   unscheduled a return value of 'ClockUnscheduled' is returned.
+  --   
+  --   Periodic callbacks scheduled async will be repeadedly called
+  --   automatically until it is unscheduled. To schedule a sync
+  --   periodic callback, 'clockIDWait' should be called repeatedly.
+  --   
+  --   The async callbacks can happen from any thread, either provided
+  --   by the core or from a streaming thread. The application should
+  --   be prepared for this.
+  --   
+  --   A 'ClockID' that has been unscheduled cannot be used again for
+  --   any wait operation; a new 'ClockID' should be created.
+  --   
+  --   It is possible to perform a blocking wait on the same 'ClockID'
+  --   from multiple threads. However, registering the same 'ClockID'
+  --   for multiple async notifications is not possible, the callback
+  --   will only be called for the thread registering the entry last.
+  --   
+  --   These clock operations do not operate on the stream time, so
+  --   the callbacks will also occur when not in the playing state as
+  --   if the clock just keeps on running. Some clocks however do not
+  --   progress when the element that provided the clock is not
+  --   playing.
+  --   
+  --   When a clock has the 'ClockFlagCanSetMaster' flag set, it can
+  --   be slaved to another 'Clock' with 'clockSetMaster'. The clock
+  --   will then automatically be synchronized to this master clock by
+  --   repeatedly sampling the master clock and the slave clock and
+  --   recalibrating the slave clock with 'clockSetCalibration'. This
+  --   feature is mostly useful for plugins that have an internal
+  --   clock but must operate with another clock selected by the
+  --   GstPipeline. They can track the offset and rate difference of
+  --   their internal clock relative to the master clock by using the
+  --   'clockGetCalibration' function.
+  --   
+  --   The master\/slave synchronisation can be tuned with the
+  --   the 'clockTimeout', 'clockWindowSize' and 'clockWindowThreshold' properties.
+  --   The 'clockTimeout' property defines the interval to
+  --   sample the master clock and run the calibration
+  --   functions. 'clockWindowSize' defines the number of samples to
+  --   use when calibrating and 'clockWindowThreshold' defines the
+  --   minimum number of samples before the calibration is performed.
+
+-- * Types
   Clock,
   ClockClass,
   castToClock,
   toClock,
   
+  -- | A time value measured in nanoseconds.
   ClockTime,
+  
+  -- | The 'ClockTime' value representing an invalid time.
   clockTimeNone,
   clockTimeIsValid,
+  
+  -- | The 'ClockTime' value representing 1 second, i.e. 1e9.
   second,
+  -- | The 'ClockTime' value representing 1 millisecond, i.e. 1e6.
   msecond,
+  -- | The 'ClockTime' value representing 1 microsecond, i.e. 1e3.
   usecond,
+  -- | The 'ClockTime' value representing 1 nanosecond, i.e. 1.
   nsecond,
-  
+  -- | A value holding the difference between two 'ClockTime's.
   ClockTimeDiff,
+  -- | An opaque identifier for a timer event.
+  ClockID,
+  -- | An enumeration type returned by 'clockIDWait'.
   ClockReturn(..),
-  ClockID,
-  
+  -- | The flags a 'Clock' may have.
   ClockFlags(..),
   clockGetFlags,
   clockSetFlags,
   clockUnsetFlags,
-  
+
+-- * Clock Operations  
   clockAddObservation,
   clockSetMaster,
   clockGetMaster,

                       liftM4 (\a b c d ->
                               (fromIntegral a,
                                fromIntegral b,
                                (fromIntegral c) % (fromIntegral d)))
                              (peek internalPtr)
                              (peek externalPtr)
                              (peek rateNumPtr)
                              (peek rateDenomPtr)

clockSetCalibration :: ClockClass clock
                    => clock
                    -> ClockTime
                    -> ClockTime
                    -> Ratio ClockTime
                    -> IO ()
clockSetCalibration clock internal external rate =
    {# call clock_set_calibration #} (toClock clock)

  clockIDWait,
  clockIDUnschedule,
  
-- * Clock Properties
  clockTimeout,
  clockWindowSize,
  clockWindowThreshold
