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

'GI.Gst.Structs.Context.Context' is a container object used to store contexts like a device
context, a display server connection and similar concepts that should
be shared between multiple elements.

Applications can set a context on a complete pipeline by using
'GI.Gst.Objects.Element.elementSetContext', which will then be propagated to all
child elements. Elements can handle these in 'GI.Gst.Structs.ElementClass.ElementClass'.@/set_context/@()
and merge them with the context information they already have.

When an element needs a context it will do the following actions in this
order until one step succeeds:
1. Check if the element already has a context
2. Query downstream with GST_QUERY_CONTEXT for the context
3. Query upstream with GST_QUERY_CONTEXT for the context
4. Post a GST_MESSAGE_NEED_CONTEXT message on the bus with the required
   context types and afterwards check if a usable context was set now
5. Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT message
   on the bus.

Bins will catch GST_MESSAGE_NEED_CONTEXT messages and will set any previously
known context on the element that asks for it if possible. Otherwise the
application should provide one if it can.

'GI.Gst.Structs.Context.Context'\<!-- -->s can be persistent.
A persistent 'GI.Gst.Structs.Context.Context' is kept in elements when they reach
'GI.Gst.Enums.StateNull', non-persistent ones will be removed.
Also, a non-persistent context won\'t override a previous persistent
context set to an element.

/Since: 1.2/
-}

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

module GI.Gst.Structs.Context
    (

-- * Exported types
    Context(..)                             ,
    noContext                               ,


 -- * Methods
-- ** getContextType #method:getContextType#

#if ENABLE_OVERLOADING
    ContextGetContextTypeMethodInfo         ,
#endif
    contextGetContextType                   ,


-- ** getStructure #method:getStructure#

#if ENABLE_OVERLOADING
    ContextGetStructureMethodInfo           ,
#endif
    contextGetStructure                     ,


-- ** hasContextType #method:hasContextType#

#if ENABLE_OVERLOADING
    ContextHasContextTypeMethodInfo         ,
#endif
    contextHasContextType                   ,


-- ** isPersistent #method:isPersistent#

#if ENABLE_OVERLOADING
    ContextIsPersistentMethodInfo           ,
#endif
    contextIsPersistent                     ,


-- ** new #method:new#

    contextNew                              ,


-- ** writableStructure #method:writableStructure#

#if ENABLE_OVERLOADING
    ContextWritableStructureMethodInfo      ,
#endif
    contextWritableStructure                ,




    ) 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 {-# SOURCE #-} qualified GI.Gst.Structs.Structure as Gst.Structure

-- | Memory-managed wrapper type.
newtype Context = Context (ManagedPtr Context)
foreign import ccall "gst_context_get_type" c_gst_context_get_type ::
    IO GType

instance BoxedObject Context where
    boxedType _ = c_gst_context_get_type

-- | A convenience alias for `Nothing` :: `Maybe` `Context`.
noContext :: Maybe Context
noContext = Nothing


#if ENABLE_OVERLOADING
instance O.HasAttributeList Context
type instance O.AttributeList Context = ContextAttributeList
type ContextAttributeList = ('[ ] :: [(Symbol, *)])
#endif

-- method Context::new
-- method type : Constructor
-- Args : [Arg {argCName = "context_type", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "Context type", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "persistent", argType = TBasicType TBoolean, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "Persistent context", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "Context"}))
-- throws : False
-- Skip return : False

foreign import ccall "gst_context_new" gst_context_new ::
    CString ->                              -- context_type : TBasicType TUTF8
    CInt ->                                 -- persistent : TBasicType TBoolean
    IO (Ptr Context)

{- |
Create a new context.

/Since: 1.2/
-}
contextNew ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    T.Text
    {- ^ /@contextType@/: Context type -}
    -> Bool
    {- ^ /@persistent@/: Persistent context -}
    -> m Context
    {- ^ __Returns:__ The new context. -}
contextNew contextType persistent = liftIO $ do
    contextType' <- textToCString contextType
    let persistent' = (fromIntegral . fromEnum) persistent
    result <- gst_context_new contextType' persistent'
    checkUnexpectedReturnNULL "contextNew" result
    result' <- (wrapBoxed Context) result
    freeMem contextType'
    return result'

#if ENABLE_OVERLOADING
#endif

-- method Context::get_context_type
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "context", argType = TInterface (Name {namespace = "Gst", name = "Context"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "The #GstContext.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TUTF8)
-- throws : False
-- Skip return : False

foreign import ccall "gst_context_get_context_type" gst_context_get_context_type ::
    Ptr Context ->                          -- context : TInterface (Name {namespace = "Gst", name = "Context"})
    IO CString

{- |
Get the type of /@context@/.

/Since: 1.2/
-}
contextGetContextType ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Context
    {- ^ /@context@/: The 'GI.Gst.Structs.Context.Context'. -}
    -> m T.Text
    {- ^ __Returns:__ The type of the context. -}
contextGetContextType context = liftIO $ do
    context' <- unsafeManagedPtrGetPtr context
    result <- gst_context_get_context_type context'
    checkUnexpectedReturnNULL "contextGetContextType" result
    result' <- cstringToText result
    touchManagedPtr context
    return result'

#if ENABLE_OVERLOADING
data ContextGetContextTypeMethodInfo
instance (signature ~ (m T.Text), MonadIO m) => O.MethodInfo ContextGetContextTypeMethodInfo Context signature where
    overloadedMethod _ = contextGetContextType

#endif

-- method Context::get_structure
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "context", argType = TInterface (Name {namespace = "Gst", name = "Context"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "The #GstContext.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "Structure"}))
-- throws : False
-- Skip return : False

foreign import ccall "gst_context_get_structure" gst_context_get_structure ::
    Ptr Context ->                          -- context : TInterface (Name {namespace = "Gst", name = "Context"})
    IO (Ptr Gst.Structure.Structure)

{- |
Access the structure of the context.

/Since: 1.2/
-}
contextGetStructure ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Context
    {- ^ /@context@/: The 'GI.Gst.Structs.Context.Context'. -}
    -> m Gst.Structure.Structure
    {- ^ __Returns:__ The structure of the context. The structure is
still owned by the context, which means that you should not modify it,
free it and that the pointer becomes invalid when you free the context. -}
contextGetStructure context = liftIO $ do
    context' <- unsafeManagedPtrGetPtr context
    result <- gst_context_get_structure context'
    checkUnexpectedReturnNULL "contextGetStructure" result
    result' <- (newBoxed Gst.Structure.Structure) result
    touchManagedPtr context
    return result'

#if ENABLE_OVERLOADING
data ContextGetStructureMethodInfo
instance (signature ~ (m Gst.Structure.Structure), MonadIO m) => O.MethodInfo ContextGetStructureMethodInfo Context signature where
    overloadedMethod _ = contextGetStructure

#endif

-- method Context::has_context_type
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "context", argType = TInterface (Name {namespace = "Gst", name = "Context"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "The #GstContext.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "context_type", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "Context type to check.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TBoolean)
-- throws : False
-- Skip return : False

foreign import ccall "gst_context_has_context_type" gst_context_has_context_type ::
    Ptr Context ->                          -- context : TInterface (Name {namespace = "Gst", name = "Context"})
    CString ->                              -- context_type : TBasicType TUTF8
    IO CInt

{- |
Checks if /@context@/ has /@contextType@/.

/Since: 1.2/
-}
contextHasContextType ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Context
    {- ^ /@context@/: The 'GI.Gst.Structs.Context.Context'. -}
    -> T.Text
    {- ^ /@contextType@/: Context type to check. -}
    -> m Bool
    {- ^ __Returns:__ 'True' if /@context@/ has /@contextType@/. -}
contextHasContextType context contextType = liftIO $ do
    context' <- unsafeManagedPtrGetPtr context
    contextType' <- textToCString contextType
    result <- gst_context_has_context_type context' contextType'
    let result' = (/= 0) result
    touchManagedPtr context
    freeMem contextType'
    return result'

#if ENABLE_OVERLOADING
data ContextHasContextTypeMethodInfo
instance (signature ~ (T.Text -> m Bool), MonadIO m) => O.MethodInfo ContextHasContextTypeMethodInfo Context signature where
    overloadedMethod _ = contextHasContextType

#endif

-- method Context::is_persistent
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "context", argType = TInterface (Name {namespace = "Gst", name = "Context"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "The #GstContext.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TBoolean)
-- throws : False
-- Skip return : False

foreign import ccall "gst_context_is_persistent" gst_context_is_persistent ::
    Ptr Context ->                          -- context : TInterface (Name {namespace = "Gst", name = "Context"})
    IO CInt

{- |
Check if /@context@/ is persistent.

/Since: 1.2/
-}
contextIsPersistent ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Context
    {- ^ /@context@/: The 'GI.Gst.Structs.Context.Context'. -}
    -> m Bool
    {- ^ __Returns:__ 'True' if the context is persistent. -}
contextIsPersistent context = liftIO $ do
    context' <- unsafeManagedPtrGetPtr context
    result <- gst_context_is_persistent context'
    let result' = (/= 0) result
    touchManagedPtr context
    return result'

#if ENABLE_OVERLOADING
data ContextIsPersistentMethodInfo
instance (signature ~ (m Bool), MonadIO m) => O.MethodInfo ContextIsPersistentMethodInfo Context signature where
    overloadedMethod _ = contextIsPersistent

#endif

-- method Context::writable_structure
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "context", argType = TInterface (Name {namespace = "Gst", name = "Context"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "The #GstContext.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "Structure"}))
-- throws : False
-- Skip return : False

foreign import ccall "gst_context_writable_structure" gst_context_writable_structure ::
    Ptr Context ->                          -- context : TInterface (Name {namespace = "Gst", name = "Context"})
    IO (Ptr Gst.Structure.Structure)

{- |
Get a writable version of the structure.

/Since: 1.2/
-}
contextWritableStructure ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Context
    {- ^ /@context@/: The 'GI.Gst.Structs.Context.Context'. -}
    -> m Gst.Structure.Structure
    {- ^ __Returns:__ The structure of the context. The structure is still
owned by the context, which means that you should not free it and
that the pointer becomes invalid when you free the context.
This function checks if /@context@/ is writable. -}
contextWritableStructure context = liftIO $ do
    context' <- unsafeManagedPtrGetPtr context
    result <- gst_context_writable_structure context'
    checkUnexpectedReturnNULL "contextWritableStructure" result
    result' <- (wrapBoxed Gst.Structure.Structure) result
    touchManagedPtr context
    return result'

#if ENABLE_OVERLOADING
data ContextWritableStructureMethodInfo
instance (signature ~ (m Gst.Structure.Structure), MonadIO m) => O.MethodInfo ContextWritableStructureMethodInfo Context signature where
    overloadedMethod _ = contextWritableStructure

#endif

#if ENABLE_OVERLOADING
type family ResolveContextMethod (t :: Symbol) (o :: *) :: * where
    ResolveContextMethod "hasContextType" o = ContextHasContextTypeMethodInfo
    ResolveContextMethod "isPersistent" o = ContextIsPersistentMethodInfo
    ResolveContextMethod "writableStructure" o = ContextWritableStructureMethodInfo
    ResolveContextMethod "getContextType" o = ContextGetContextTypeMethodInfo
    ResolveContextMethod "getStructure" o = ContextGetStructureMethodInfo
    ResolveContextMethod l o = O.MethodResolutionFailed l o

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