{- |
Copyright  : Will Thompson, Iñaki García Etxebarria and Jonas Platte
License    : LGPL-2.1
Maintainer : Iñaki García Etxebarria (garetxe@gmail.com)

The GStreamer core provides a GstSystemClock based on the system time.
Asynchronous callbacks are scheduled from an internal thread.

Clock implementors are encouraged to subclass this systemclock as it
implements the async notification.

Subclasses can however override all of the important methods for sync and
async notifications to implement their own callback methods or blocking
wait operations.
-}

module GI.Gst.Objects.SystemClock
    ( 

-- * Exported types
    SystemClock(..)                         ,
    IsSystemClock                           ,
    toSystemClock                           ,
    noSystemClock                           ,


 -- * Methods
-- ** obtain #method:obtain#
    systemClockObtain                       ,


-- ** setDefault #method:setDefault#
    systemClockSetDefault                   ,




 -- * Properties
-- ** clockType #attr:clockType#
#if defined(ENABLE_OVERLOADING) && !defined(__HADDOCK_VERSION__)
    SystemClockClockTypePropertyInfo        ,
#endif
    constructSystemClockClockType           ,
    getSystemClockClockType                 ,
    setSystemClockClockType                 ,
#if defined(ENABLE_OVERLOADING) && !defined(__HADDOCK_VERSION__)
    systemClockClockType                    ,
#endif




    ) where

import Data.GI.Base.ShortPrelude
import qualified Data.GI.Base.ShortPrelude as SP
import qualified Data.GI.Base.Overloading as O
import qualified Prelude as P

import qualified Data.GI.Base.Attributes as GI.Attributes
import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GVariant as B.GVariant
import qualified Data.GI.Base.GParamSpec as B.GParamSpec
import qualified Data.GI.Base.CallStack as B.CallStack
import qualified Data.Text as T
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map
import qualified Foreign.Ptr as FP

import qualified GI.GObject.Objects.Object as GObject.Object
import {-# SOURCE #-} qualified GI.Gst.Enums as Gst.Enums
import {-# SOURCE #-} qualified GI.Gst.Objects.Clock as Gst.Clock
import {-# SOURCE #-} qualified GI.Gst.Objects.Object as Gst.Object

newtype SystemClock = SystemClock (ManagedPtr SystemClock)
foreign import ccall "gst_system_clock_get_type"
    c_gst_system_clock_get_type :: IO GType

instance GObject SystemClock where
    gobjectType _ = c_gst_system_clock_get_type
    

class GObject o => IsSystemClock o
#if MIN_VERSION_base(4,9,0)
instance {-# OVERLAPPABLE #-} (GObject a, O.UnknownAncestorError SystemClock a) =>
    IsSystemClock a
#endif
instance IsSystemClock SystemClock
instance Gst.Clock.IsClock SystemClock
instance Gst.Object.IsObject SystemClock
instance GObject.Object.IsObject SystemClock

toSystemClock :: (MonadIO m, IsSystemClock o) => o -> m SystemClock
toSystemClock = liftIO . unsafeCastTo SystemClock

noSystemClock :: Maybe SystemClock
noSystemClock = Nothing

#if defined(ENABLE_OVERLOADING) && !defined(__HADDOCK_VERSION__)
type family ResolveSystemClockMethod (t :: Symbol) (o :: *) :: * where
    ResolveSystemClockMethod "addControlBinding" o = Gst.Object.ObjectAddControlBindingMethodInfo
    ResolveSystemClockMethod "addObservation" o = Gst.Clock.ClockAddObservationMethodInfo
    ResolveSystemClockMethod "addObservationUnapplied" o = Gst.Clock.ClockAddObservationUnappliedMethodInfo
    ResolveSystemClockMethod "adjustUnlocked" o = Gst.Clock.ClockAdjustUnlockedMethodInfo
    ResolveSystemClockMethod "adjustWithCalibration" o = Gst.Clock.ClockAdjustWithCalibrationMethodInfo
    ResolveSystemClockMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
    ResolveSystemClockMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
    ResolveSystemClockMethod "defaultError" o = Gst.Object.ObjectDefaultErrorMethodInfo
    ResolveSystemClockMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
    ResolveSystemClockMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
    ResolveSystemClockMethod "hasActiveControlBindings" o = Gst.Object.ObjectHasActiveControlBindingsMethodInfo
    ResolveSystemClockMethod "hasAncestor" o = Gst.Object.ObjectHasAncestorMethodInfo
    ResolveSystemClockMethod "hasAsAncestor" o = Gst.Object.ObjectHasAsAncestorMethodInfo
    ResolveSystemClockMethod "hasAsParent" o = Gst.Object.ObjectHasAsParentMethodInfo
    ResolveSystemClockMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
    ResolveSystemClockMethod "isSynced" o = Gst.Clock.ClockIsSyncedMethodInfo
    ResolveSystemClockMethod "newPeriodicId" o = Gst.Clock.ClockNewPeriodicIdMethodInfo
    ResolveSystemClockMethod "newSingleShotId" o = Gst.Clock.ClockNewSingleShotIdMethodInfo
    ResolveSystemClockMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
    ResolveSystemClockMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
    ResolveSystemClockMethod "periodicIdReinit" o = Gst.Clock.ClockPeriodicIdReinitMethodInfo
    ResolveSystemClockMethod "ref" o = Gst.Object.ObjectRefMethodInfo
    ResolveSystemClockMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
    ResolveSystemClockMethod "removeControlBinding" o = Gst.Object.ObjectRemoveControlBindingMethodInfo
    ResolveSystemClockMethod "replaceData" o = GObject.Object.ObjectReplaceDataMethodInfo
    ResolveSystemClockMethod "replaceQdata" o = GObject.Object.ObjectReplaceQdataMethodInfo
    ResolveSystemClockMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
    ResolveSystemClockMethod "singleShotIdReinit" o = Gst.Clock.ClockSingleShotIdReinitMethodInfo
    ResolveSystemClockMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
    ResolveSystemClockMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
    ResolveSystemClockMethod "suggestNextSync" o = Gst.Object.ObjectSuggestNextSyncMethodInfo
    ResolveSystemClockMethod "syncValues" o = Gst.Object.ObjectSyncValuesMethodInfo
    ResolveSystemClockMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
    ResolveSystemClockMethod "unadjustUnlocked" o = Gst.Clock.ClockUnadjustUnlockedMethodInfo
    ResolveSystemClockMethod "unadjustWithCalibration" o = Gst.Clock.ClockUnadjustWithCalibrationMethodInfo
    ResolveSystemClockMethod "unparent" o = Gst.Object.ObjectUnparentMethodInfo
    ResolveSystemClockMethod "unref" o = Gst.Object.ObjectUnrefMethodInfo
    ResolveSystemClockMethod "waitForSync" o = Gst.Clock.ClockWaitForSyncMethodInfo
    ResolveSystemClockMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
    ResolveSystemClockMethod "getCalibration" o = Gst.Clock.ClockGetCalibrationMethodInfo
    ResolveSystemClockMethod "getControlBinding" o = Gst.Object.ObjectGetControlBindingMethodInfo
    ResolveSystemClockMethod "getControlRate" o = Gst.Object.ObjectGetControlRateMethodInfo
    ResolveSystemClockMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
    ResolveSystemClockMethod "getGValueArray" o = Gst.Object.ObjectGetGValueArrayMethodInfo
    ResolveSystemClockMethod "getInternalTime" o = Gst.Clock.ClockGetInternalTimeMethodInfo
    ResolveSystemClockMethod "getMaster" o = Gst.Clock.ClockGetMasterMethodInfo
    ResolveSystemClockMethod "getName" o = Gst.Object.ObjectGetNameMethodInfo
    ResolveSystemClockMethod "getParent" o = Gst.Object.ObjectGetParentMethodInfo
    ResolveSystemClockMethod "getPathString" o = Gst.Object.ObjectGetPathStringMethodInfo
    ResolveSystemClockMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
    ResolveSystemClockMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
    ResolveSystemClockMethod "getResolution" o = Gst.Clock.ClockGetResolutionMethodInfo
    ResolveSystemClockMethod "getTime" o = Gst.Clock.ClockGetTimeMethodInfo
    ResolveSystemClockMethod "getTimeout" o = Gst.Clock.ClockGetTimeoutMethodInfo
    ResolveSystemClockMethod "getValue" o = Gst.Object.ObjectGetValueMethodInfo
    ResolveSystemClockMethod "setCalibration" o = Gst.Clock.ClockSetCalibrationMethodInfo
    ResolveSystemClockMethod "setControlBindingDisabled" o = Gst.Object.ObjectSetControlBindingDisabledMethodInfo
    ResolveSystemClockMethod "setControlBindingsDisabled" o = Gst.Object.ObjectSetControlBindingsDisabledMethodInfo
    ResolveSystemClockMethod "setControlRate" o = Gst.Object.ObjectSetControlRateMethodInfo
    ResolveSystemClockMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
    ResolveSystemClockMethod "setMaster" o = Gst.Clock.ClockSetMasterMethodInfo
    ResolveSystemClockMethod "setName" o = Gst.Object.ObjectSetNameMethodInfo
    ResolveSystemClockMethod "setParent" o = Gst.Object.ObjectSetParentMethodInfo
    ResolveSystemClockMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
    ResolveSystemClockMethod "setResolution" o = Gst.Clock.ClockSetResolutionMethodInfo
    ResolveSystemClockMethod "setSynced" o = Gst.Clock.ClockSetSyncedMethodInfo
    ResolveSystemClockMethod "setTimeout" o = Gst.Clock.ClockSetTimeoutMethodInfo
    ResolveSystemClockMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveSystemClockMethod t SystemClock, O.MethodInfo info SystemClock p) => O.IsLabelProxy t (SystemClock -> p) where
    fromLabelProxy _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)

#if MIN_VERSION_base(4,9,0)
instance (info ~ ResolveSystemClockMethod t SystemClock, O.MethodInfo info SystemClock p) => O.IsLabel t (SystemClock -> p) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#else
    fromLabel _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#endif
#endif

#endif

-- VVV Prop "clock-type"
   -- Type: TInterface (Name {namespace = "Gst", name = "ClockType"})
   -- Flags: [PropertyReadable,PropertyWritable]
   -- Nullable: (Nothing,Nothing)

getSystemClockClockType :: (MonadIO m, IsSystemClock o) => o -> m Gst.Enums.ClockType
getSystemClockClockType obj = liftIO $ getObjectPropertyEnum obj "clock-type"

setSystemClockClockType :: (MonadIO m, IsSystemClock o) => o -> Gst.Enums.ClockType -> m ()
setSystemClockClockType obj val = liftIO $ setObjectPropertyEnum obj "clock-type" val

constructSystemClockClockType :: (IsSystemClock o) => Gst.Enums.ClockType -> IO (GValueConstruct o)
constructSystemClockClockType val = constructObjectPropertyEnum "clock-type" val

#if defined(ENABLE_OVERLOADING) && !defined(__HADDOCK_VERSION__)
data SystemClockClockTypePropertyInfo
instance AttrInfo SystemClockClockTypePropertyInfo where
    type AttrAllowedOps SystemClockClockTypePropertyInfo = '[ 'AttrSet, 'AttrConstruct, 'AttrGet]
    type AttrSetTypeConstraint SystemClockClockTypePropertyInfo = (~) Gst.Enums.ClockType
    type AttrBaseTypeConstraint SystemClockClockTypePropertyInfo = IsSystemClock
    type AttrGetType SystemClockClockTypePropertyInfo = Gst.Enums.ClockType
    type AttrLabel SystemClockClockTypePropertyInfo = "clock-type"
    type AttrOrigin SystemClockClockTypePropertyInfo = SystemClock
    attrGet _ = getSystemClockClockType
    attrSet _ = setSystemClockClockType
    attrConstruct _ = constructSystemClockClockType
    attrClear _ = undefined
#endif

#if defined(ENABLE_OVERLOADING) && !defined(__HADDOCK_VERSION__)
instance O.HasAttributeList SystemClock
type instance O.AttributeList SystemClock = SystemClockAttributeList
type SystemClockAttributeList = ('[ '("clockType", SystemClockClockTypePropertyInfo), '("name", Gst.Object.ObjectNamePropertyInfo), '("parent", Gst.Object.ObjectParentPropertyInfo), '("timeout", Gst.Clock.ClockTimeoutPropertyInfo), '("windowSize", Gst.Clock.ClockWindowSizePropertyInfo), '("windowThreshold", Gst.Clock.ClockWindowThresholdPropertyInfo)] :: [(Symbol, *)])
#endif

#if defined(ENABLE_OVERLOADING) && !defined(__HADDOCK_VERSION__)
systemClockClockType :: AttrLabelProxy "clockType"
systemClockClockType = AttrLabelProxy

#endif

#if defined(ENABLE_OVERLOADING) && !defined(__HADDOCK_VERSION__)
type instance O.SignalList SystemClock = SystemClockSignalList
type SystemClockSignalList = ('[ '("deepNotify", Gst.Object.ObjectDeepNotifySignalInfo), '("notify", GObject.Object.ObjectNotifySignalInfo), '("synced", Gst.Clock.ClockSyncedSignalInfo)] :: [(Symbol, *)])

#endif

-- method SystemClock::obtain
-- method type : MemberFunction
-- Args : []
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "Clock"}))
-- throws : False
-- Skip return : False

foreign import ccall "gst_system_clock_obtain" gst_system_clock_obtain :: 
    IO (Ptr Gst.Clock.Clock)

{- |
Get a handle to the default system clock. The refcount of the
clock will be increased so you need to unref the clock after
usage.
-}
systemClockObtain ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    m Gst.Clock.Clock
    {- ^ __Returns:__ the default clock.

MT safe. -}
systemClockObtain  = liftIO $ do
    result <- gst_system_clock_obtain
    checkUnexpectedReturnNULL "systemClockObtain" result
    result' <- (wrapObject Gst.Clock.Clock) result
    return result'

#if defined(ENABLE_OVERLOADING) && !defined(__HADDOCK_VERSION__)
#endif

-- method SystemClock::set_default
-- method type : MemberFunction
-- Args : [Arg {argCName = "new_clock", argType = TInterface (Name {namespace = "Gst", name = "Clock"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstClock", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "gst_system_clock_set_default" gst_system_clock_set_default :: 
    Ptr Gst.Clock.Clock ->                  -- new_clock : TInterface (Name {namespace = "Gst", name = "Clock"})
    IO ()

{- |
Sets the default system clock that can be obtained with
'GI.Gst.Objects.SystemClock.systemClockObtain'.

This is mostly used for testing and debugging purposes when you
want to have control over the time reported by the default system
clock.

MT safe.

@since 1.4
-}
systemClockSetDefault ::
    (B.CallStack.HasCallStack, MonadIO m, Gst.Clock.IsClock a) =>
    a
    {- ^ /@newClock@/: a 'GI.Gst.Objects.Clock.Clock' -}
    -> m ()
systemClockSetDefault newClock = liftIO $ do
    newClock' <- unsafeManagedPtrCastPtr newClock
    gst_system_clock_set_default newClock'
    touchManagedPtr newClock
    return ()

#if defined(ENABLE_OVERLOADING) && !defined(__HADDOCK_VERSION__)
#endif