gi-gst-1.0.18: GI/Gst/Structs/Promise.hs
{- |
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 'GI.Gst.Structs.Promise.Promise' object implements the container for values that may
be available later. i.e. a Future or a Promise in
\<ulink url=\"https:\/\/en.wikipedia.org\/wiki\/Futures_and_promises\">https:\/\/en.wikipedia.org\/wiki\/Futures_and_promises\<\/ulink>
As with all Future\/Promise-like functionality, there is the concept of the
producer of the value and the consumer of the value.
A 'GI.Gst.Structs.Promise.Promise' is created with 'GI.Gst.Structs.Promise.promiseNew' by the consumer and passed
to the producer to avoid thread safety issues with the change callback.
A 'GI.Gst.Structs.Promise.Promise' can be replied to with a value (or an error) by the producer
with 'GI.Gst.Structs.Promise.promiseReply'. 'GI.Gst.Structs.Promise.promiseInterrupt' is for the consumer to
indicate to the producer that the value is not needed anymore and producing
that value can stop. The /@gSTPROMISERESULTEXPIRED@/ state set by a call
to 'GI.Gst.Structs.Promise.promiseExpire' indicates to the consumer that a value will never
be produced and is intended to be called by a third party that implements
some notion of message handling such as 'GI.Gst.Objects.Bus.Bus'.
A callback can also be installed at 'GI.Gst.Structs.Promise.Promise' creation for
result changes with 'GI.Gst.Structs.Promise.promiseNewWithChangeFunc'.
The change callback can be used to chain @/GstPromises/@\'s together as in the
following example.
=== /C code/
>
>const GstStructure *reply;
>GstPromise *p;
>if (gst_promise_wait (promise) != GST_PROMISE_RESULT_REPLIED)
> return; // interrupted or expired value
>reply = gst_promise_get_reply (promise);
>if (error in reply)
> return; // propagate error
>p = gst_promise_new_with_change_func (another_promise_change_func, user_data, notify);
>pass p to promise-using API
Each 'GI.Gst.Structs.Promise.Promise' starts out with a 'GI.Gst.Enums.PromiseResult' of
'GI.Gst.Enums.PromiseResultPending' and only ever transitions once
into one of the other 'GI.Gst.Enums.PromiseResult'\'s.
In order to support multi-threaded code, 'GI.Gst.Structs.Promise.promiseReply',
'GI.Gst.Structs.Promise.promiseInterrupt' and 'GI.Gst.Structs.Promise.promiseExpire' may all be from
different threads with some restrictions and the final result of the promise
is whichever call is made first. There are two restrictions on ordering:
1. That 'GI.Gst.Structs.Promise.promiseReply' and 'GI.Gst.Structs.Promise.promiseInterrupt' cannot be called
after 'GI.Gst.Structs.Promise.promiseExpire'
2. That 'GI.Gst.Structs.Promise.promiseReply' and 'GI.Gst.Structs.Promise.promiseInterrupt'
cannot be called twice.
The change function set with 'GI.Gst.Structs.Promise.promiseNewWithChangeFunc' is
called directly from either the 'GI.Gst.Structs.Promise.promiseReply',
'GI.Gst.Structs.Promise.promiseInterrupt' or 'GI.Gst.Structs.Promise.promiseExpire' and can be called
from an arbitrary thread. 'GI.Gst.Structs.Promise.Promise' using APIs can restrict this to
a single thread or a subset of threads but that is entirely up to the API
that uses 'GI.Gst.Structs.Promise.Promise'.
/Since: 1.14/
-}
#define ENABLE_OVERLOADING (MIN_VERSION_haskell_gi_overloading(1,0,0) \
&& !defined(__HADDOCK_VERSION__))
module GI.Gst.Structs.Promise
(
-- * Exported types
Promise(..) ,
newZeroPromise ,
noPromise ,
-- * Methods
-- ** expire #method:expire#
#if ENABLE_OVERLOADING
PromiseExpireMethodInfo ,
#endif
promiseExpire ,
-- ** getReply #method:getReply#
#if ENABLE_OVERLOADING
PromiseGetReplyMethodInfo ,
#endif
promiseGetReply ,
-- ** interrupt #method:interrupt#
#if ENABLE_OVERLOADING
PromiseInterruptMethodInfo ,
#endif
promiseInterrupt ,
-- ** new #method:new#
promiseNew ,
-- ** newWithChangeFunc #method:newWithChangeFunc#
promiseNewWithChangeFunc ,
-- ** reply #method:reply#
#if ENABLE_OVERLOADING
PromiseReplyMethodInfo ,
#endif
promiseReply ,
-- ** wait #method:wait#
#if ENABLE_OVERLOADING
PromiseWaitMethodInfo ,
#endif
promiseWait ,
-- * Properties
-- ** parent #attr:parent#
{- | parent 'GI.Gst.Structs.MiniObject.MiniObject'
-}
getPromiseParent ,
#if ENABLE_OVERLOADING
promise_parent ,
#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.GLib.Callbacks as GLib.Callbacks
import qualified GI.Gst.Callbacks as Gst.Callbacks
import {-# SOURCE #-} qualified GI.Gst.Enums as Gst.Enums
import {-# SOURCE #-} qualified GI.Gst.Structs.MiniObject as Gst.MiniObject
import {-# SOURCE #-} qualified GI.Gst.Structs.Structure as Gst.Structure
-- | Memory-managed wrapper type.
newtype Promise = Promise (ManagedPtr Promise)
foreign import ccall "gst_promise_get_type" c_gst_promise_get_type ::
IO GType
instance BoxedObject Promise where
boxedType _ = c_gst_promise_get_type
-- | Construct a `Promise` struct initialized to zero.
newZeroPromise :: MonadIO m => m Promise
newZeroPromise = liftIO $ callocBoxedBytes 64 >>= wrapBoxed Promise
instance tag ~ 'AttrSet => Constructible Promise tag where
new _ attrs = do
o <- newZeroPromise
GI.Attributes.set o attrs
return o
-- | A convenience alias for `Nothing` :: `Maybe` `Promise`.
noPromise :: Maybe Promise
noPromise = Nothing
{- |
Get the value of the “@parent@” field.
When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to
@
'Data.GI.Base.Attributes.get' promise #parent
@
-}
getPromiseParent :: MonadIO m => Promise -> m Gst.MiniObject.MiniObject
getPromiseParent s = liftIO $ withManagedPtr s $ \ptr -> do
let val = ptr `plusPtr` 0 :: (Ptr Gst.MiniObject.MiniObject)
val' <- (newPtr Gst.MiniObject.MiniObject) val
return val'
#if ENABLE_OVERLOADING
data PromiseParentFieldInfo
instance AttrInfo PromiseParentFieldInfo where
type AttrAllowedOps PromiseParentFieldInfo = '[ 'AttrGet]
type AttrSetTypeConstraint PromiseParentFieldInfo = (~) (Ptr Gst.MiniObject.MiniObject)
type AttrBaseTypeConstraint PromiseParentFieldInfo = (~) Promise
type AttrGetType PromiseParentFieldInfo = Gst.MiniObject.MiniObject
type AttrLabel PromiseParentFieldInfo = "parent"
type AttrOrigin PromiseParentFieldInfo = Promise
attrGet _ = getPromiseParent
attrSet _ = undefined
attrConstruct = undefined
attrClear _ = undefined
promise_parent :: AttrLabelProxy "parent"
promise_parent = AttrLabelProxy
#endif
#if ENABLE_OVERLOADING
instance O.HasAttributeList Promise
type instance O.AttributeList Promise = PromiseAttributeList
type PromiseAttributeList = ('[ '("parent", PromiseParentFieldInfo)] :: [(Symbol, *)])
#endif
-- method Promise::new
-- method type : Constructor
-- Args : []
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "Promise"}))
-- throws : False
-- Skip return : False
foreign import ccall "gst_promise_new" gst_promise_new ::
IO (Ptr Promise)
{- |
/No description available in the introspection data./
/Since: 1.14/
-}
promiseNew ::
(B.CallStack.HasCallStack, MonadIO m) =>
m Promise
{- ^ __Returns:__ a new 'GI.Gst.Structs.Promise.Promise' -}
promiseNew = liftIO $ do
result <- gst_promise_new
checkUnexpectedReturnNULL "promiseNew" result
result' <- (wrapBoxed Promise) result
return result'
#if ENABLE_OVERLOADING
#endif
-- method Promise::new_with_change_func
-- method type : Constructor
-- Args : [Arg {argCName = "func", argType = TInterface (Name {namespace = "Gst", name = "PromiseChangeFunc"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstPromiseChangeFunc to call", sinceVersion = Nothing}, argScope = ScopeTypeNotified, argClosure = 1, argDestroy = 2, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "user_data", argType = TBasicType TPtr, direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "argument to call @func with", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "notify", argType = TInterface (Name {namespace = "GLib", name = "DestroyNotify"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "notification function that @user_data is no longer needed", sinceVersion = Nothing}, argScope = ScopeTypeAsync, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "Promise"}))
-- throws : False
-- Skip return : False
foreign import ccall "gst_promise_new_with_change_func" gst_promise_new_with_change_func ::
FunPtr Gst.Callbacks.C_PromiseChangeFunc -> -- func : TInterface (Name {namespace = "Gst", name = "PromiseChangeFunc"})
Ptr () -> -- user_data : TBasicType TPtr
FunPtr GLib.Callbacks.C_DestroyNotify -> -- notify : TInterface (Name {namespace = "GLib", name = "DestroyNotify"})
IO (Ptr Promise)
{- |
/@func@/ will be called exactly once when transitioning out of
'GI.Gst.Enums.PromiseResultPending' into any of the other 'GI.Gst.Enums.PromiseResult'
states.
/Since: 1.14/
-}
promiseNewWithChangeFunc ::
(B.CallStack.HasCallStack, MonadIO m) =>
Gst.Callbacks.PromiseChangeFunc
{- ^ /@func@/: a 'GI.Gst.Callbacks.PromiseChangeFunc' to call -}
-> m Promise
{- ^ __Returns:__ a new 'GI.Gst.Structs.Promise.Promise' -}
promiseNewWithChangeFunc func = liftIO $ do
func' <- Gst.Callbacks.mk_PromiseChangeFunc (Gst.Callbacks.wrap_PromiseChangeFunc Nothing (Gst.Callbacks.drop_closures_PromiseChangeFunc func))
let userData = castFunPtrToPtr func'
let notify = safeFreeFunPtrPtr
result <- gst_promise_new_with_change_func func' userData notify
checkUnexpectedReturnNULL "promiseNewWithChangeFunc" result
result' <- (wrapBoxed Promise) result
return result'
#if ENABLE_OVERLOADING
#endif
-- method Promise::expire
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "promise", argType = TInterface (Name {namespace = "Gst", name = "Promise"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstPromise", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False
foreign import ccall "gst_promise_expire" gst_promise_expire ::
Ptr Promise -> -- promise : TInterface (Name {namespace = "Gst", name = "Promise"})
IO ()
{- |
Expire a /@promise@/. This will wake up any waiters with
'GI.Gst.Enums.PromiseResultExpired'. Called by a message loop when the parent
message is handled and\/or destroyed (possibly unanswered).
/Since: 1.14/
-}
promiseExpire ::
(B.CallStack.HasCallStack, MonadIO m) =>
Promise
{- ^ /@promise@/: a 'GI.Gst.Structs.Promise.Promise' -}
-> m ()
promiseExpire promise = liftIO $ do
promise' <- unsafeManagedPtrGetPtr promise
gst_promise_expire promise'
touchManagedPtr promise
return ()
#if ENABLE_OVERLOADING
data PromiseExpireMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.MethodInfo PromiseExpireMethodInfo Promise signature where
overloadedMethod _ = promiseExpire
#endif
-- method Promise::get_reply
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "promise", argType = TInterface (Name {namespace = "Gst", name = "Promise"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstPromise", 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_promise_get_reply" gst_promise_get_reply ::
Ptr Promise -> -- promise : TInterface (Name {namespace = "Gst", name = "Promise"})
IO (Ptr Gst.Structure.Structure)
{- |
Retrieve the reply set on /@promise@/. /@promise@/ must be in
'GI.Gst.Enums.PromiseResultReplied' and the returned structure is owned by /@promise@/
/Since: 1.14/
-}
promiseGetReply ::
(B.CallStack.HasCallStack, MonadIO m) =>
Promise
{- ^ /@promise@/: a 'GI.Gst.Structs.Promise.Promise' -}
-> m Gst.Structure.Structure
{- ^ __Returns:__ The reply set on /@promise@/ -}
promiseGetReply promise = liftIO $ do
promise' <- unsafeManagedPtrGetPtr promise
result <- gst_promise_get_reply promise'
checkUnexpectedReturnNULL "promiseGetReply" result
result' <- (newBoxed Gst.Structure.Structure) result
touchManagedPtr promise
return result'
#if ENABLE_OVERLOADING
data PromiseGetReplyMethodInfo
instance (signature ~ (m Gst.Structure.Structure), MonadIO m) => O.MethodInfo PromiseGetReplyMethodInfo Promise signature where
overloadedMethod _ = promiseGetReply
#endif
-- method Promise::interrupt
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "promise", argType = TInterface (Name {namespace = "Gst", name = "Promise"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstPromise", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False
foreign import ccall "gst_promise_interrupt" gst_promise_interrupt ::
Ptr Promise -> -- promise : TInterface (Name {namespace = "Gst", name = "Promise"})
IO ()
{- |
Interrupt waiting for a /@promise@/. This will wake up any waiters with
'GI.Gst.Enums.PromiseResultInterrupted'. Called when the consumer does not want
the value produced anymore.
/Since: 1.14/
-}
promiseInterrupt ::
(B.CallStack.HasCallStack, MonadIO m) =>
Promise
{- ^ /@promise@/: a 'GI.Gst.Structs.Promise.Promise' -}
-> m ()
promiseInterrupt promise = liftIO $ do
promise' <- unsafeManagedPtrGetPtr promise
gst_promise_interrupt promise'
touchManagedPtr promise
return ()
#if ENABLE_OVERLOADING
data PromiseInterruptMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.MethodInfo PromiseInterruptMethodInfo Promise signature where
overloadedMethod _ = promiseInterrupt
#endif
-- method Promise::reply
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "promise", argType = TInterface (Name {namespace = "Gst", name = "Promise"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstPromise", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "s", argType = TInterface (Name {namespace = "Gst", name = "Structure"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstStructure with the the reply contents", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False
foreign import ccall "gst_promise_reply" gst_promise_reply ::
Ptr Promise -> -- promise : TInterface (Name {namespace = "Gst", name = "Promise"})
Ptr Gst.Structure.Structure -> -- s : TInterface (Name {namespace = "Gst", name = "Structure"})
IO ()
{- |
Set a reply on /@promise@/. This will wake up any waiters with
'GI.Gst.Enums.PromiseResultReplied'. Called by the producer of the value to
indicate success (or failure).
If /@promise@/ has already been interrupted by the consumer, then this reply
is not visible to the consumer.
/Since: 1.14/
-}
promiseReply ::
(B.CallStack.HasCallStack, MonadIO m) =>
Promise
{- ^ /@promise@/: a 'GI.Gst.Structs.Promise.Promise' -}
-> Gst.Structure.Structure
{- ^ /@s@/: a 'GI.Gst.Structs.Structure.Structure' with the the reply contents -}
-> m ()
promiseReply promise s = liftIO $ do
promise' <- unsafeManagedPtrGetPtr promise
s' <- B.ManagedPtr.disownBoxed s
gst_promise_reply promise' s'
touchManagedPtr promise
touchManagedPtr s
return ()
#if ENABLE_OVERLOADING
data PromiseReplyMethodInfo
instance (signature ~ (Gst.Structure.Structure -> m ()), MonadIO m) => O.MethodInfo PromiseReplyMethodInfo Promise signature where
overloadedMethod _ = promiseReply
#endif
-- method Promise::wait
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "promise", argType = TInterface (Name {namespace = "Gst", name = "Promise"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GstPromise", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Gst", name = "PromiseResult"}))
-- throws : False
-- Skip return : False
foreign import ccall "gst_promise_wait" gst_promise_wait ::
Ptr Promise -> -- promise : TInterface (Name {namespace = "Gst", name = "Promise"})
IO CUInt
{- |
Wait for /@promise@/ to move out of the 'GI.Gst.Enums.PromiseResultPending' state.
If /@promise@/ is not in 'GI.Gst.Enums.PromiseResultPending' then it will return
immediately with the current result.
/Since: 1.14/
-}
promiseWait ::
(B.CallStack.HasCallStack, MonadIO m) =>
Promise
{- ^ /@promise@/: a 'GI.Gst.Structs.Promise.Promise' -}
-> m Gst.Enums.PromiseResult
{- ^ __Returns:__ the result of the promise -}
promiseWait promise = liftIO $ do
promise' <- unsafeManagedPtrGetPtr promise
result <- gst_promise_wait promise'
let result' = (toEnum . fromIntegral) result
touchManagedPtr promise
return result'
#if ENABLE_OVERLOADING
data PromiseWaitMethodInfo
instance (signature ~ (m Gst.Enums.PromiseResult), MonadIO m) => O.MethodInfo PromiseWaitMethodInfo Promise signature where
overloadedMethod _ = promiseWait
#endif
#if ENABLE_OVERLOADING
type family ResolvePromiseMethod (t :: Symbol) (o :: *) :: * where
ResolvePromiseMethod "expire" o = PromiseExpireMethodInfo
ResolvePromiseMethod "interrupt" o = PromiseInterruptMethodInfo
ResolvePromiseMethod "reply" o = PromiseReplyMethodInfo
ResolvePromiseMethod "wait" o = PromiseWaitMethodInfo
ResolvePromiseMethod "getReply" o = PromiseGetReplyMethodInfo
ResolvePromiseMethod l o = O.MethodResolutionFailed l o
instance (info ~ ResolvePromiseMethod t Promise, O.MethodInfo info Promise p) => OL.IsLabel t (Promise -> 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