    {-# LANGUAGE GeneralizedNewtypeDeriving #-}

    {-# LINE 2 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}
    -- GIMP Toolkit (GTK) Binding for Haskell: binding to gstreamer -*-haskell-*-
    --
    -- Author : Peter Gavin
    -- Created: 1-Apr-2007
    --
    -- Copyright (c) 2007 Peter Gavin
    --
    -- This library is free software: you can redistribute it and/or
    -- modify it under the terms of the GNU Lesser General Public License
    -- as published by the Free Software Foundation, either version 3 of
    -- the License, or (at your option) any later version.
    --
    -- This library is distributed in the hope that it will be useful,
    -- but WITHOUT ANY WARRANTY; without even the implied warranty of
    -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    -- Lesser General Public License for more details.
    --
    -- You should have received a copy of the GNU Lesser General Public
    -- License along with this program. If not, see
    -- <http:
    --
    -- GStreamer, the C library which this Haskell library depends on, is
    -- available under LGPL Version 2. The documentation included with
    -- this library is based on the original GStreamer documentation.
    --
    -- |
    -- Maintainer : gtk2hs-devel@lists.sourceforge.net
    -- Stability : alpha
    -- Portability : portable (depends on GHC)
    --
    -- A structure describing sets of media formats.
    module Media.Streaming.GStreamer.Core.Caps (

    -- * Detail
      -- | 'Caps' (short for /capabilities/) are lightweight objects
      -- describing media types. They are composed of arrays of
      -- 'Structure's.
      --
      -- 'Caps' are exposed on 'PadTemplate's to describe all the
      -- possible types a given 'Pad' can handle. They are also stored
      -- in the 'Registry' along with the description of an 'Element'.
      --
      -- 'Caps' can be retrieved from an 'Element'\'s 'Pad's using the
      -- 'padGetCaps' function. The returned 'Caps' describes the possible
      -- types that the pad can handle or produce at runtime.
      --
      -- 'Caps' are also attached to 'Buffers' to describe the type of
      -- the contained data using the function 'bufferSetCaps'. 'Caps'
      -- attached to a buffer allow for format negotiation upstream and
      -- downstream.
      --
      -- 'Caps' are /fixed/ when they have no properties with ranges or
      -- lists. Use 'capsIsFixed' to test for fixed caps. Only fixed
      -- caps may be set on a 'Pad' or 'Buffer'.

    -- * Types
      Caps,
      capsNone,
      capsAny,

    -- * Caps Operations
      capsSize,
      capsGetStructure,
      capsIsEmpty,
      capsIsFixed,
      capsIsEqual,
      capsIsEqualFixed,
      capsIsAlwaysCompatible,
      capsIsSubset,
      capsIntersect,
      capsUnion,
      capsSubtract,
      capsNormalize,
      capsFromString,
      capsToString,

    -- * Caps Mutation
      CapsM,
      capsCreate,
      capsModify,
      capsAppendStructure,

      capsMergeStructure,
      capsRemoveStructure,

      capsTruncate

      ) where

    {-# LINE 92 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}

    import Control.Monad (liftM)
    import Control.Monad.Reader
    import System.Glib.FFI
    import System.Glib.UTFString
    import Media.Streaming.GStreamer.Core.Types
    {-# LINE 98 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}

    -- | A 'Caps' that represents an undefined media type.
    capsNone :: Caps
    capsNone =
        unsafePerformIO $ gst_caps_new_empty >>= takeCaps

    -- | A 'Caps' that represents all possible media types.
    capsAny :: Caps
    capsAny =
        unsafePerformIO $ gst_caps_new_any >>= takeCaps

    -- | Get the number of structures contained in the 'Caps'.
    capsSize :: Caps -- ^ @caps@ - a 'Caps'
             -> Word -- ^ the number of structures contained in the 'Caps'
    capsSize caps =
        fromIntegral $ unsafePerformIO $ (\(Caps arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_get_size argPtr1) caps

    -- | Get the 'Structure' at the given index.
    capsGetStructure :: Caps -- ^ @caps@ - a 'Caps'
                     -> Word -- ^ @index@ - the index of the 'Structure'
                     -> Maybe Structure -- ^ the 'Structure' at the given index, or 'Nothing'
                                        -- if @index@ is invalid
    capsGetStructure caps index =
        unsafePerformIO $
            (\(Caps arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_get_structure argPtr1 arg2) caps (fromIntegral index) >>=
                maybePeek peekStructure

    -- | Create a new 'Caps' containing only the 'Structure' at the given
    -- index of the caps.
    capsCopyNth :: Caps -- ^ @caps@ - a 'Caps'
                -> Word -- ^ @index@ - the index of the 'Structure'
                -> Maybe Caps -- ^ the new 'Caps', or 'Nothing'
                              -- if @index@ is invalid
    capsCopyNth caps index =
        unsafePerformIO $
            (\(Caps arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_copy_nth argPtr1 arg2) caps (fromIntegral index) >>=
                maybePeek takeCaps

    -- | Determine whether @caps@ represents no media formats.
    capsIsEmpty :: Caps -- ^ @caps@ - a 'Caps'
                -> Bool -- ^ 'True' if @caps@ is empty, otherwise 'False'
    capsIsEmpty caps =
        toBool $ unsafePerformIO $
            (\(Caps arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_is_empty argPtr1) caps

    -- | Determine whether the @caps@ is fixed; that is, if it has exactly
    -- one structure, and each field in the structure describes a fixed type.
    capsIsFixed :: Caps -- ^ @caps@ - a 'Caps'
                -> Bool -- ^ 'True' if @caps@ is fixed, otherwise 'False'
    capsIsFixed caps =
        toBool $ unsafePerformIO $
            (\(Caps arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_is_fixed argPtr1) caps

    -- | Returns 'True' if the caps represent the same set of capabilities.
    --
    -- This function does not work reliably if optional properties for
    -- 'Caps' are included on one 'Caps' but omitted on the other.
    capsIsEqual :: Caps -- ^ @caps1@ - the first 'Caps'
                -> Caps -- ^ @caps2@ - the second 'Caps'
                -> Bool -- ^ 'True' if both 'Caps' represent the same set
                        -- of capabilities.
    capsIsEqual caps1 caps2 =
        toBool $ unsafePerformIO $
            (\(Caps arg1) (Caps arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_caps_is_equal argPtr1 argPtr2) caps1 caps2

    instance Eq Caps where
        (==) = capsIsEqual

    -- | Returns 'True' if the caps are equal. The caps must both be
    -- fixed.
    capsIsEqualFixed :: Caps -- ^ @caps1@ - the first 'Caps'
                     -> Caps -- ^ @caps2@ - the second 'Caps'
                     -> Bool -- ^ 'True' if both 'Caps' represent the same set
                             -- of capabilities
    capsIsEqualFixed caps1 caps2 =
        toBool $ unsafePerformIO $
            (\(Caps arg1) (Caps arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_caps_is_equal_fixed argPtr1 argPtr2) caps1 caps2

    -- | Returns 'True' if every media format in the first caps is also
    -- contained by the second. That is, the first is a subset of the
    -- second.
    capsIsAlwaysCompatible :: Caps -- ^ @caps1@ - the first 'Caps'
                           -> Caps -- ^ @caps2@ - the second 'Caps'
                           -> Bool -- ^ 'True' if @caps1@ is a subset of @caps2@, otherwise 'False'
    capsIsAlwaysCompatible caps1 caps2 =
        toBool $ unsafePerformIO $
            (\(Caps arg1) (Caps arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_caps_is_always_compatible argPtr1 argPtr2) caps1 caps2

    -- | Returns 'True' if all caps represented by the first argument are
    -- also represented by the second.
    --
    -- This function does not work reliably if optional properties for
    -- caps are included on one caps and omitted on the other.
    capsIsSubset :: Caps -- ^ @caps1@ - the first 'Caps'
                 -> Caps -- ^ @caps2@ - the second 'Caps'
                 -> Bool -- ^ 'True' if @caps1@ is a subset of @caps2@, otherwise 'False'
    capsIsSubset caps1 caps2 =
        toBool $ unsafePerformIO $
            (\(Caps arg1) (Caps arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_caps_is_subset argPtr1 argPtr2) caps1 caps2

    -- | Creates a new caps containing all the formats that are common to
    -- both of the caps.
    capsIntersect :: Caps -- ^ @caps1@ - the first 'Caps'
                  -> Caps -- ^ @caps2@ - the second 'Caps'
                  -> Caps -- ^ a new 'Caps' containing all capabilities present
                          -- in both @caps1@ and @caps2@
    capsIntersect caps1 caps2 =
        unsafePerformIO $
            (\(Caps arg1) (Caps arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_caps_intersect argPtr1 argPtr2) caps1 caps2 >>=
                takeCaps

    -- | Creates a new caps containing all the formats that are common to
    -- either of the caps. If either of the structures are equivalient
    -- to 'capsAny', the result will be 'capsAny'.
    capsUnion :: Caps -- ^ @caps1@ - the first 'Caps'
              -> Caps -- ^ @caps2@ - the second 'Caps'
              -> Caps -- ^ a new 'Caps' containing all capabilities present
                      -- in either @caps1@ and @caps2@
    capsUnion caps1 caps2 =
        unsafePerformIO $
            (\(Caps arg1) (Caps arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_caps_union argPtr1 argPtr2) caps1 caps2 >>=
                takeCaps

    -- | Creates a new caps containing all the formats that are in the
    -- first but not the second.
    capsSubtract :: Caps -- ^ @caps1@ - the first 'Caps'
                 -> Caps -- ^ @caps2@ - the second 'Caps'
                 -> Caps -- ^ a new 'Caps' containing all capabilities present
                         -- in @caps1@ but not @caps2@
    capsSubtract caps1 caps2 =
        unsafePerformIO $
            (\(Caps arg1) (Caps arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_caps_subtract argPtr1 argPtr2) caps1 caps2 >>=
                takeCaps

    -- | Creates a new caps that represents the same set of formats as the
    -- argument, but that contains no lists.
    capsNormalize :: Caps -- ^ @caps@ - a 'Caps'
                  -> Caps -- ^ the new, normalized 'Caps'
    capsNormalize caps =
        unsafePerformIO $
            (\(Caps arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_normalize argPtr1) caps >>= takeCaps

    -- | Converts the argument to a string representation. The string can
    -- be converted back to a caps using 'capsFromString'.
    capsToString :: Caps -- ^ @caps@ - a 'Caps'
                 -> String -- ^ the string representation of 'Caps'
    capsToString caps =
        unsafePerformIO $
            (\(Caps arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_to_string argPtr1) caps >>= readUTFString

    -- | Read a caps from a string.
    capsFromString :: String -- ^ @string@ - the string representation of a 'Caps'
                   -> Maybe Caps -- ^ the new 'Caps', or 'Nothing' if @string@ is invalid
    capsFromString string =
        unsafePerformIO $
            withUTFString string gst_caps_from_string >>=
                maybePeek takeCaps

    -- | A 'Monad' for sequencing modifications to a 'Caps'.
    newtype CapsM a =
        CapsM (ReaderT (Ptr Caps) IO a)
        deriving (Functor, Monad)

    askCapsPtr :: CapsM (Ptr Caps)
    askCapsPtr = CapsM $ ask

    marshalCapsModify :: IO (Ptr Caps)
                      -> CapsM a
                      -> (Caps, a)
    marshalCapsModify mkCaps (CapsM action) =
        unsafePerformIO $
            do ptr <- mkCaps
               result <- runReaderT action ptr
               caps <- takeCaps ptr
               return (caps, result)

    -- | Create a caps and mutate it according to the given action.
    capsCreate :: CapsM a -- ^ @mutate@ - the mutating action
               -> (Caps, a) -- ^ the new 'Caps' and the action's result
    capsCreate mutate =
        marshalCapsModify
            gst_caps_new_empty
    {-# LINE 280 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}
            mutate

    -- | Copy a caps and mutate it according to the given action.
    capsModify :: Caps -- ^ @caps@ - the 'Caps' to modify
               -> CapsM a -- ^ @mutate@ - the mutating action
               -> (Caps, a) -- ^ the new 'Caps' and the action's result
    capsModify caps mutate =
        marshalCapsModify ((\(Caps arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_copy argPtr1) caps) mutate

    -- | Append the given structure to the current caps.
    capsAppendStructure :: Structure -- ^ @structure@ - the 'Structure' to append to the current 'Caps'
                        -> CapsM ()
    capsAppendStructure structure = do
      capsPtr <- askCapsPtr
      CapsM $ liftIO $ withStructure structure $ \structurePtr ->
          do structurePtr' <- gst_structure_copy structurePtr
             gst_caps_append_structure capsPtr structurePtr
      where _ = (\(Caps arg1) (Structure arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_caps_append_structure argPtr1 argPtr2)
    {-# LINE 298 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}
            _ = (\(Structure arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_structure_copy argPtr1)
    {-# LINE 299 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}

    -- | Append the structure to the current caps, if it is not already
    -- expressed by the caps.
    --
    -- Since 0.10.10.
    capsMergeStructure :: Structure -- ^ @structure@ - the 'Structure' to merge with the current 'Caps'
                       -> CapsM ()
    capsMergeStructure structure = do
      capsPtr <- askCapsPtr
      CapsM $ liftIO $ withStructure structure $ \structurePtr ->
          do structurePtr' <- gst_structure_copy structurePtr
             gst_caps_merge_structure capsPtr structurePtr
      where _ = (\(Caps arg1) (Structure arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_caps_merge_structure argPtr1 argPtr2)
    {-# LINE 313 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}
            _ = (\(Structure arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_structure_copy argPtr1)
    {-# LINE 314 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}

    -- | Removes the structure at the given index from the current caps.
    capsRemoveStructure :: Word -- ^ @idx@ - the index of the 'Structure' to remove
                        -> CapsM ()
    capsRemoveStructure idx = do
      capsPtr <- askCapsPtr
      CapsM $ liftIO $ gst_caps_remove_structure capsPtr $ fromIntegral idx
      where _ = (\(Caps arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_remove_structure argPtr1 arg2)
    {-# LINE 322 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}

    -- | Discard all but the first structure from the current caps.
    capsTruncate :: CapsM ()
    capsTruncate = do
      capsPtr <- askCapsPtr
      CapsM $ liftIO $ gst_caps_truncate capsPtr
      where _ = (\(Caps arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_caps_truncate argPtr1)
    {-# LINE 330 "./Media/Streaming/GStreamer/Core/Caps.chs" #-}

    foreign import ccall safe "gst_caps_new_empty"
      gst_caps_new_empty :: (IO (Ptr Caps))

    foreign import ccall safe "gst_caps_new_any"
      gst_caps_new_any :: (IO (Ptr Caps))

    foreign import ccall safe "gst_caps_get_size"
      gst_caps_get_size :: ((Ptr Caps) -> (IO CUInt))

    foreign import ccall safe "gst_caps_get_structure"
      gst_caps_get_structure :: ((Ptr Caps) -> (CUInt -> (IO (Ptr Structure))))

    foreign import ccall safe "gst_caps_copy_nth"
      gst_caps_copy_nth :: ((Ptr Caps) -> (CUInt -> (IO (Ptr Caps))))

    foreign import ccall safe "gst_caps_is_empty"
      gst_caps_is_empty :: ((Ptr Caps) -> (IO CInt))

    foreign import ccall safe "gst_caps_is_fixed"
      gst_caps_is_fixed :: ((Ptr Caps) -> (IO CInt))

    foreign import ccall safe "gst_caps_is_equal"
      gst_caps_is_equal :: ((Ptr Caps) -> ((Ptr Caps) -> (IO CInt)))

    foreign import ccall safe "gst_caps_is_equal_fixed"
      gst_caps_is_equal_fixed :: ((Ptr Caps) -> ((Ptr Caps) -> (IO CInt)))

    foreign import ccall safe "gst_caps_is_always_compatible"
      gst_caps_is_always_compatible :: ((Ptr Caps) -> ((Ptr Caps) -> (IO CInt)))

    foreign import ccall safe "gst_caps_is_subset"
      gst_caps_is_subset :: ((Ptr Caps) -> ((Ptr Caps) -> (IO CInt)))

    foreign import ccall safe "gst_caps_intersect"
      gst_caps_intersect :: ((Ptr Caps) -> ((Ptr Caps) -> (IO (Ptr Caps))))

    foreign import ccall safe "gst_caps_union"
      gst_caps_union :: ((Ptr Caps) -> ((Ptr Caps) -> (IO (Ptr Caps))))

    foreign import ccall safe "gst_caps_subtract"
      gst_caps_subtract :: ((Ptr Caps) -> ((Ptr Caps) -> (IO (Ptr Caps))))

    foreign import ccall safe "gst_caps_normalize"
      gst_caps_normalize :: ((Ptr Caps) -> (IO (Ptr Caps)))

    foreign import ccall safe "gst_caps_to_string"
      gst_caps_to_string :: ((Ptr Caps) -> (IO (Ptr CChar)))

    foreign import ccall safe "gst_caps_from_string"
      gst_caps_from_string :: ((Ptr CChar) -> (IO (Ptr Caps)))

    foreign import ccall safe "gst_caps_copy"
      gst_caps_copy :: ((Ptr Caps) -> (IO (Ptr Caps)))

    foreign import ccall safe "gst_caps_append_structure"
      gst_caps_append_structure :: ((Ptr Caps) -> ((Ptr Structure) -> (IO ())))

    foreign import ccall safe "gst_structure_copy"
      gst_structure_copy :: ((Ptr Structure) -> (IO (Ptr Structure)))

    foreign import ccall safe "gst_caps_merge_structure"
      gst_caps_merge_structure :: ((Ptr Caps) -> ((Ptr Structure) -> (IO ())))

    foreign import ccall safe "gst_caps_remove_structure"
      gst_caps_remove_structure :: ((Ptr Caps) -> (CUInt -> (IO ())))

    foreign import ccall safe "gst_caps_truncate"
      gst_caps_truncate :: ((Ptr Caps) -> (IO ()))