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

Memory is usually created by allocators with a 'GI.Gst.Objects.Allocator.allocatorAlloc'
method call. When 'Nothing' is used as the allocator, the default allocator will
be used.

New allocators can be registered with 'GI.Gst.Objects.Allocator.allocatorRegister'.
Allocators are identified by name and can be retrieved with
'GI.Gst.Objects.Allocator.allocatorFind'. 'GI.Gst.Objects.Allocator.allocatorSetDefault' can be used to change the
default allocator.

New memory can be created with 'GI.Gst.Structs.Memory.memoryNewWrapped' that wraps the memory
allocated elsewhere.
-}

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

module GI.Gst.Objects.Allocator
    (

-- * Exported types
    Allocator(..)                           ,
    IsAllocator                             ,
    toAllocator                             ,
    noAllocator                             ,


 -- * Methods
-- ** alloc #method:alloc#

#if ENABLE_OVERLOADING
    AllocatorAllocMethodInfo                ,
#endif
    allocatorAlloc                          ,


-- ** find #method:find#

    allocatorFind                           ,


-- ** free #method:free#

#if ENABLE_OVERLOADING
    AllocatorFreeMethodInfo                 ,
#endif
    allocatorFree                           ,


-- ** register #method:register#

    allocatorRegister                       ,


-- ** setDefault #method:setDefault#

#if ENABLE_OVERLOADING
    AllocatorSetDefaultMethodInfo           ,
#endif
    allocatorSetDefault                     ,




    ) 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.Objects.Object as Gst.Object
import {-# SOURCE #-} qualified GI.Gst.Structs.AllocationParams as Gst.AllocationParams
import {-# SOURCE #-} qualified GI.Gst.Structs.Memory as Gst.Memory

-- | Memory-managed wrapper type.
newtype Allocator = Allocator (ManagedPtr Allocator)
foreign import ccall "gst_allocator_get_type"
    c_gst_allocator_get_type :: IO GType

instance GObject Allocator where
    gobjectType = c_gst_allocator_get_type


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

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

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

-- | A convenience alias for `Nothing` :: `Maybe` `Allocator`.
noAllocator :: Maybe Allocator
noAllocator = Nothing

#if ENABLE_OVERLOADING
type family ResolveAllocatorMethod (t :: Symbol) (o :: *) :: * where
    ResolveAllocatorMethod "addControlBinding" o = Gst.Object.ObjectAddControlBindingMethodInfo
    ResolveAllocatorMethod "alloc" o = AllocatorAllocMethodInfo
    ResolveAllocatorMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
    ResolveAllocatorMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
    ResolveAllocatorMethod "defaultError" o = Gst.Object.ObjectDefaultErrorMethodInfo
    ResolveAllocatorMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
    ResolveAllocatorMethod "free" o = AllocatorFreeMethodInfo
    ResolveAllocatorMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
    ResolveAllocatorMethod "getv" o = GObject.Object.ObjectGetvMethodInfo
    ResolveAllocatorMethod "hasActiveControlBindings" o = Gst.Object.ObjectHasActiveControlBindingsMethodInfo
    ResolveAllocatorMethod "hasAncestor" o = Gst.Object.ObjectHasAncestorMethodInfo
    ResolveAllocatorMethod "hasAsAncestor" o = Gst.Object.ObjectHasAsAncestorMethodInfo
    ResolveAllocatorMethod "hasAsParent" o = Gst.Object.ObjectHasAsParentMethodInfo
    ResolveAllocatorMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
    ResolveAllocatorMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
    ResolveAllocatorMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
    ResolveAllocatorMethod "ref" o = Gst.Object.ObjectRefMethodInfo
    ResolveAllocatorMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
    ResolveAllocatorMethod "removeControlBinding" o = Gst.Object.ObjectRemoveControlBindingMethodInfo
    ResolveAllocatorMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
    ResolveAllocatorMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
    ResolveAllocatorMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
    ResolveAllocatorMethod "suggestNextSync" o = Gst.Object.ObjectSuggestNextSyncMethodInfo
    ResolveAllocatorMethod "syncValues" o = Gst.Object.ObjectSyncValuesMethodInfo
    ResolveAllocatorMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
    ResolveAllocatorMethod "unparent" o = Gst.Object.ObjectUnparentMethodInfo
    ResolveAllocatorMethod "unref" o = Gst.Object.ObjectUnrefMethodInfo
    ResolveAllocatorMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
    ResolveAllocatorMethod "getControlBinding" o = Gst.Object.ObjectGetControlBindingMethodInfo
    ResolveAllocatorMethod "getControlRate" o = Gst.Object.ObjectGetControlRateMethodInfo
    ResolveAllocatorMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
    ResolveAllocatorMethod "getGValueArray" o = Gst.Object.ObjectGetGValueArrayMethodInfo
    ResolveAllocatorMethod "getName" o = Gst.Object.ObjectGetNameMethodInfo
    ResolveAllocatorMethod "getParent" o = Gst.Object.ObjectGetParentMethodInfo
    ResolveAllocatorMethod "getPathString" o = Gst.Object.ObjectGetPathStringMethodInfo
    ResolveAllocatorMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
    ResolveAllocatorMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
    ResolveAllocatorMethod "getValue" o = Gst.Object.ObjectGetValueMethodInfo
    ResolveAllocatorMethod "setControlBindingDisabled" o = Gst.Object.ObjectSetControlBindingDisabledMethodInfo
    ResolveAllocatorMethod "setControlBindingsDisabled" o = Gst.Object.ObjectSetControlBindingsDisabledMethodInfo
    ResolveAllocatorMethod "setControlRate" o = Gst.Object.ObjectSetControlRateMethodInfo
    ResolveAllocatorMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
    ResolveAllocatorMethod "setDefault" o = AllocatorSetDefaultMethodInfo
    ResolveAllocatorMethod "setName" o = Gst.Object.ObjectSetNameMethodInfo
    ResolveAllocatorMethod "setParent" o = Gst.Object.ObjectSetParentMethodInfo
    ResolveAllocatorMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
    ResolveAllocatorMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveAllocatorMethod t Allocator, O.MethodInfo info Allocator p) => OL.IsLabel t (Allocator -> 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

#if ENABLE_OVERLOADING
instance O.HasAttributeList Allocator
type instance O.AttributeList Allocator = AllocatorAttributeList
type AllocatorAttributeList = ('[ '("name", Gst.Object.ObjectNamePropertyInfo), '("parent", Gst.Object.ObjectParentPropertyInfo)] :: [(Symbol, *)])
#endif

#if ENABLE_OVERLOADING
#endif

#if ENABLE_OVERLOADING
type instance O.SignalList Allocator = AllocatorSignalList
type AllocatorSignalList = ('[ '("deepNotify", Gst.Object.ObjectDeepNotifySignalInfo), '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, *)])

#endif

-- method Allocator::alloc
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "allocator", argType = TInterface (Name {namespace = "Gst", name = "Allocator"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstAllocator to use", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "size", argType = TBasicType TUInt64, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "size of the visible memory area", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "params", argType = TInterface (Name {namespace = "Gst", name = "AllocationParams"}), direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "optional parameters", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "Memory"}))
-- throws : False
-- Skip return : False

foreign import ccall "gst_allocator_alloc" gst_allocator_alloc ::
    Ptr Allocator ->                        -- allocator : TInterface (Name {namespace = "Gst", name = "Allocator"})
    Word64 ->                               -- size : TBasicType TUInt64
    Ptr Gst.AllocationParams.AllocationParams -> -- params : TInterface (Name {namespace = "Gst", name = "AllocationParams"})
    IO (Ptr Gst.Memory.Memory)

{- |
Use /@allocator@/ to allocate a new memory block with memory that is at least
/@size@/ big.

The optional /@params@/ can specify the prefix and padding for the memory. If
'Nothing' is passed, no flags, no extra prefix\/padding and a default alignment is
used.

The prefix\/padding will be filled with 0 if flags contains
@/GST_MEMORY_FLAG_ZERO_PREFIXED/@ and @/GST_MEMORY_FLAG_ZERO_PADDED/@ respectively.

When /@allocator@/ is 'Nothing', the default allocator will be used.

The alignment in /@params@/ is given as a bitmask so that /@align@/ + 1 equals
the amount of bytes to align to. For example, to align to 8 bytes,
use an alignment of 7.
-}
allocatorAlloc ::
    (B.CallStack.HasCallStack, MonadIO m, IsAllocator a) =>
    a
    {- ^ /@allocator@/: a 'GI.Gst.Objects.Allocator.Allocator' to use -}
    -> Word64
    {- ^ /@size@/: size of the visible memory area -}
    -> Maybe (Gst.AllocationParams.AllocationParams)
    {- ^ /@params@/: optional parameters -}
    -> m (Maybe Gst.Memory.Memory)
    {- ^ __Returns:__ a new 'GI.Gst.Structs.Memory.Memory'. -}
allocatorAlloc allocator size params = liftIO $ do
    allocator' <- unsafeManagedPtrCastPtr allocator
    maybeParams <- case params of
        Nothing -> return nullPtr
        Just jParams -> do
            jParams' <- unsafeManagedPtrGetPtr jParams
            return jParams'
    result <- gst_allocator_alloc allocator' size maybeParams
    maybeResult <- convertIfNonNull result $ \result' -> do
        result'' <- (wrapBoxed Gst.Memory.Memory) result'
        return result''
    touchManagedPtr allocator
    whenJust params touchManagedPtr
    return maybeResult

#if ENABLE_OVERLOADING
data AllocatorAllocMethodInfo
instance (signature ~ (Word64 -> Maybe (Gst.AllocationParams.AllocationParams) -> m (Maybe Gst.Memory.Memory)), MonadIO m, IsAllocator a) => O.MethodInfo AllocatorAllocMethodInfo a signature where
    overloadedMethod _ = allocatorAlloc

#endif

-- method Allocator::free
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "allocator", argType = TInterface (Name {namespace = "Gst", name = "Allocator"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstAllocator to use", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "memory", argType = TInterface (Name {namespace = "Gst", name = "Memory"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the memory to free", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "gst_allocator_free" gst_allocator_free ::
    Ptr Allocator ->                        -- allocator : TInterface (Name {namespace = "Gst", name = "Allocator"})
    Ptr Gst.Memory.Memory ->                -- memory : TInterface (Name {namespace = "Gst", name = "Memory"})
    IO ()

{- |
Free /@memory@/ that was previously allocated with 'GI.Gst.Objects.Allocator.allocatorAlloc'.
-}
allocatorFree ::
    (B.CallStack.HasCallStack, MonadIO m, IsAllocator a) =>
    a
    {- ^ /@allocator@/: a 'GI.Gst.Objects.Allocator.Allocator' to use -}
    -> Gst.Memory.Memory
    {- ^ /@memory@/: the memory to free -}
    -> m ()
allocatorFree allocator memory = liftIO $ do
    allocator' <- unsafeManagedPtrCastPtr allocator
    memory' <- B.ManagedPtr.disownBoxed memory
    gst_allocator_free allocator' memory'
    touchManagedPtr allocator
    touchManagedPtr memory
    return ()

#if ENABLE_OVERLOADING
data AllocatorFreeMethodInfo
instance (signature ~ (Gst.Memory.Memory -> m ()), MonadIO m, IsAllocator a) => O.MethodInfo AllocatorFreeMethodInfo a signature where
    overloadedMethod _ = allocatorFree

#endif

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

foreign import ccall "gst_allocator_set_default" gst_allocator_set_default ::
    Ptr Allocator ->                        -- allocator : TInterface (Name {namespace = "Gst", name = "Allocator"})
    IO ()

{- |
Set the default allocator. This function takes ownership of /@allocator@/.
-}
allocatorSetDefault ::
    (B.CallStack.HasCallStack, MonadIO m, IsAllocator a) =>
    a
    {- ^ /@allocator@/: a 'GI.Gst.Objects.Allocator.Allocator' -}
    -> m ()
allocatorSetDefault allocator = liftIO $ do
    allocator' <- B.ManagedPtr.disownObject allocator
    gst_allocator_set_default allocator'
    touchManagedPtr allocator
    return ()

#if ENABLE_OVERLOADING
data AllocatorSetDefaultMethodInfo
instance (signature ~ (m ()), MonadIO m, IsAllocator a) => O.MethodInfo AllocatorSetDefaultMethodInfo a signature where
    overloadedMethod _ = allocatorSetDefault

#endif

-- method Allocator::find
-- method type : MemberFunction
-- Args : [Arg {argCName = "name", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "the name of the allocator", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "Allocator"}))
-- throws : False
-- Skip return : False

foreign import ccall "gst_allocator_find" gst_allocator_find ::
    CString ->                              -- name : TBasicType TUTF8
    IO (Ptr Allocator)

{- |
Find a previously registered allocator with /@name@/. When /@name@/ is 'Nothing', the
default allocator will be returned.
-}
allocatorFind ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Maybe (T.Text)
    {- ^ /@name@/: the name of the allocator -}
    -> m (Maybe Allocator)
    {- ^ __Returns:__ a 'GI.Gst.Objects.Allocator.Allocator' or 'Nothing' when
the allocator with /@name@/ was not registered. Use 'GI.Gst.Objects.Object.objectUnref'
to release the allocator after usage. -}
allocatorFind name = liftIO $ do
    maybeName <- case name of
        Nothing -> return nullPtr
        Just jName -> do
            jName' <- textToCString jName
            return jName'
    result <- gst_allocator_find maybeName
    maybeResult <- convertIfNonNull result $ \result' -> do
        result'' <- (wrapObject Allocator) result'
        return result''
    freeMem maybeName
    return maybeResult

#if ENABLE_OVERLOADING
#endif

-- method Allocator::register
-- method type : MemberFunction
-- Args : [Arg {argCName = "name", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the name of the allocator", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "allocator", argType = TInterface (Name {namespace = "Gst", name = "Allocator"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "#GstAllocator", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "gst_allocator_register" gst_allocator_register ::
    CString ->                              -- name : TBasicType TUTF8
    Ptr Allocator ->                        -- allocator : TInterface (Name {namespace = "Gst", name = "Allocator"})
    IO ()

{- |
Registers the memory /@allocator@/ with /@name@/. This function takes ownership of
/@allocator@/.
-}
allocatorRegister ::
    (B.CallStack.HasCallStack, MonadIO m, IsAllocator a) =>
    T.Text
    {- ^ /@name@/: the name of the allocator -}
    -> a
    {- ^ /@allocator@/: 'GI.Gst.Objects.Allocator.Allocator' -}
    -> m ()
allocatorRegister name allocator = liftIO $ do
    name' <- textToCString name
    allocator' <- B.ManagedPtr.disownObject allocator
    gst_allocator_register name' allocator'
    touchManagedPtr allocator
    freeMem name'
    return ()

#if ENABLE_OVERLOADING
#endif