{-# 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 ()))