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

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.
-}

#define ENABLE_OVERLOADING (MIN_VERSION_haskell_gi_overloading(1,0,0) \
       && !defined(__HADDOCK_VERSION__))

module GI.Gst.Objects.SystemClock
    (

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


 -- * Methods
-- ** obtain #method:obtain#

    systemClockObtain                       ,


-- ** setDefault #method:setDefault#

    systemClockSetDefault                   ,




 -- * Properties
-- ** clockType #attr:clockType#
{- | /No description available in the introspection data./
-}
#if ENABLE_OVERLOADING
    SystemClockClockTypePropertyInfo        ,
#endif
    constructSystemClockClockType           ,
    getSystemClockClockType                 ,
    setSystemClockClockType                 ,
#if ENABLE_OVERLOADING
    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.GClosure as B.GClosure
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GVariant as B.GVariant
import qualified Data.GI.Base.GValue as B.GValue
import qualified Data.GI.Base.GParamSpec as B.GParamSpec
import qualified Data.GI.Base.CallStack as B.CallStack
import qualified Data.GI.Base.Properties as B.Properties
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 GHC.OverloadedLabels as OL

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

-- | Memory-managed wrapper type.
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


-- | Type class for types which can be safely cast to `SystemClock`, for instance with `toSystemClock`.
class (GObject o, O.IsDescendantOf SystemClock o) => IsSystemClock o
instance (GObject o, O.IsDescendantOf SystemClock o) => IsSystemClock o

instance O.HasParentTypes SystemClock
type instance O.ParentTypes SystemClock = '[Gst.Clock.Clock, Gst.Object.Object, GObject.Object.Object]

-- | Cast to `SystemClock`, for types for which this is known to be safe. For general casts, use `Data.GI.Base.ManagedPtr.castTo`.
toSystemClock :: (MonadIO m, IsSystemClock o) => o -> m SystemClock
toSystemClock = liftIO . unsafeCastTo SystemClock

-- | A convenience alias for `Nothing` :: `Maybe` `SystemClock`.
noSystemClock :: Maybe SystemClock
noSystemClock = Nothing

#if ENABLE_OVERLOADING
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 "getv" o = GObject.Object.ObjectGetvMethodInfo
    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 "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) => OL.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

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

{- |
Get the value of the “@clock-type@” property.
When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to

@
'Data.GI.Base.Attributes.get' systemClock #clockType
@
-}
getSystemClockClockType :: (MonadIO m, IsSystemClock o) => o -> m Gst.Enums.ClockType
getSystemClockClockType obj = liftIO $ B.Properties.getObjectPropertyEnum obj "clock-type"

{- |
Set the value of the “@clock-type@” property.
When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to

@
'Data.GI.Base.Attributes.set' systemClock [ #clockType 'Data.GI.Base.Attributes.:=' value ]
@
-}
setSystemClockClockType :: (MonadIO m, IsSystemClock o) => o -> Gst.Enums.ClockType -> m ()
setSystemClockClockType obj val = liftIO $ B.Properties.setObjectPropertyEnum obj "clock-type" val

{- |
Construct a `GValueConstruct` with valid value for the “@clock-type@” property. This is rarely needed directly, but it is used by `Data.GI.Base.Constructible.new`.
-}
constructSystemClockClockType :: (IsSystemClock o) => Gst.Enums.ClockType -> IO (GValueConstruct o)
constructSystemClockClockType val = B.Properties.constructObjectPropertyEnum "clock-type" val

#if ENABLE_OVERLOADING
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 ENABLE_OVERLOADING
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 ENABLE_OVERLOADING
systemClockClockType :: AttrLabelProxy "clockType"
systemClockClockType = AttrLabelProxy

#endif

#if ENABLE_OVERLOADING
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 ENABLE_OVERLOADING
#endif

-- method SystemClock::set_default
-- method type : MemberFunction
-- Args : [Arg {argCName = "new_clock", argType = TInterface (Name {namespace = "Gst", name = "Clock"}), direction = DirectionIn, mayBeNull = True, 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) =>
    Maybe (a)
    {- ^ /@newClock@/: a 'GI.Gst.Objects.Clock.Clock' -}
    -> m ()
systemClockSetDefault newClock = liftIO $ do
    maybeNewClock <- case newClock of
        Nothing -> return nullPtr
        Just jNewClock -> do
            jNewClock' <- unsafeManagedPtrCastPtr jNewClock
            return jNewClock'
    gst_system_clock_set_default maybeNewClock
    whenJust newClock touchManagedPtr
    return ()

#if ENABLE_OVERLOADING
#endif