{- | 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