    {-# LINE 2 "./Media/Streaming/GStreamer/Core/Bin.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)
    --
    -- Base class for elements that can contain other elements.
    module Media.Streaming.GStreamer.Core.Bin (

    -- * Detail
      -- | 'Bin' is an element that can contain other 'Element's, allowing
      -- them to be managed as a group. 'Pad's from the child elements
      -- can be ghosted to the bin; see 'GhostPad'. This makes the bin
      -- look like any other element, and enables creation of
      -- higher-level abstractions.
      --
      -- A new 'Bin' is created with 'binNew'. Use a 'Pipeline' instead
      -- if you want to create a toplevel bin, because a normal bin
      -- doesn't have a bus or handle clock distribution of its own.
      --
      -- After the bin has been created you will typically add elements
      -- to it with 'binAdd'. You can remove elements with 'binRemove'.
      --
      -- An element can be retrieved from a bin with 'binGetByName',
      -- using the element's name. 'binGetByNameRecurseUp' is mainly
      -- used for internal purposes and will query the parent bins when
      -- the element is not found in the current bin.
      --
      -- An iterator of elements in a bin can be retrieved with
      -- 'binIterateElements'. Various other iterators exist to retrieve
      -- the elements in a bin.
      --
      -- The 'binElementAdded' signal is fired whenever a new element is
      -- added to the bin. Likewise the 'binElementRemoved' signal is
      -- fired whenever an element is removed from the bin.

    -- * Types
      Bin,
      BinClass,
      castToBin,
      gTypeBin,

    -- * Bin Operations
      binNew,
      binAdd,
      binRemove,
      binGetByName,
      binGetByNameRecurseUp,
      binGetByInterface,
      binIterateElements,
      binIterateRecurse,
      binIterateSinks,
      binIterateSorted,
      binIterateSources,
      binIterateAllByInterface,
      binFindUnconnectedPad,

    -- * Bin Signals
      binElementAdded,
      binElementRemoved

      ) where

    import Control.Exception ( bracket_ )
    import Control.Monad ( liftM )
    import System.Glib.FFI
    import System.Glib.GType ( GType )
    import System.Glib.UTFString ( withUTFString )
    import System.Glib.GList ( GList
                                                  , readGList )
    import Media.Streaming.GStreamer.Core.Types
    {-# LINE 96 "./Media/Streaming/GStreamer/Core/Bin.chs" #-}
    import Media.Streaming.GStreamer.Core.Signals
    {-# LINE 97 "./Media/Streaming/GStreamer/Core/Bin.chs" #-}

    {-# LINE 99 "./Media/Streaming/GStreamer/Core/Bin.chs" #-}

    -- | Create a new 'Bin' with the given name.
    binNew :: String -- ^ @name@ - the name to give the new 'Bin'
           -> IO Bin -- ^ the new 'Bin'
    binNew name =
        withUTFString name gst_bin_new >>= takeObject . castPtr

    -- | Add @element@ to @bin@, and set @element@'s parent to
    -- @bin@. An 'Element' can only be added to one 'Bin' at a time.
    --
    -- If any of @element@'s pads are linked to other 'Pad's, they will be
    -- unlinked before @element@ is added to @bin@.
    binAdd :: (BinClass bin, ElementClass element)
           => bin -- ^ @bin@ - a 'Bin'
           -> element -- ^ @element@ - the element to add
           -> IO Bool -- ^ 'True' if the element could be added, 'False'
                      -- if the bin does not want to accept the element
    binAdd bin element =
        liftM toBool $ (\(Bin arg1) (Element arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_bin_add argPtr1 argPtr2) (toBin bin) (toElement element)

    -- | Remove @element@ from @bin@, unparenting it as well.
    --
    -- If any @element@'s pads are linked to other pads, they will be
    -- unlinked before @element@ is added to @bin@.
    binRemove :: (BinClass bin, ElementClass element)
              => bin -- ^ @bin@ - a 'Bin'
              -> element -- ^ @element@ - the element to remove
              -> IO Bool -- ^ 'True' if @element@ could be removed, otherwise 'False'
    binRemove bin element =
        liftM toBool $ (\(Bin arg1) (Element arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gst_bin_remove argPtr1 argPtr2) (toBin bin) (toElement element)

    -- | Get the 'Element' with the given name @name@ from @bin@,
    -- recursing down through @bin@'s children. 'Nothing' is returned if no
    -- 'Element' with the given name is found.
    binGetByName :: BinClass bin
                 => bin -- ^ @bin@ - a 'Bin'
                 -> String -- ^ @name@ - the name to search for
                 -> IO (Maybe Element) -- ^ the 'Element' with the name @name@, or 'Nothing'
    binGetByName bin name =
        withUTFString name ((\(Bin arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_get_by_name argPtr1 arg2) (toBin bin)) >>= maybePeek takeObject

    -- | Get the 'Element' with the given name @name@ from @bin@,
    -- recursing up through @bin@'s parents. Returns 'Nothing' if no
    -- element with the given name is found.
    binGetByNameRecurseUp :: BinClass bin
                          => bin -- ^ @bin@ - a 'Bin'
                          -> String -- ^ @element@ - the name to search for
                          -> IO (Maybe Element) -- ^ the 'Element' with the given name, or 'Nothing'
    binGetByNameRecurseUp bin name =
        withUTFString name ((\(Bin arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_get_by_name_recurse_up argPtr1 arg2) $ toBin bin) >>=
            maybePeek takeObject

    -- | Find an 'Element' inside @bin@ that implements the interface
    -- given by @iface@. The returned 'Element' can be casted to
    -- @iface@'s type. If you want all the 'Element's that implement an
    -- interface, use 'binIterateAllByInterface'.
    --
    -- This function recurses into child bins.
    binGetByInterface :: BinClass bin
                      => bin -- ^ @bin@ - a 'Bin'
                      -> GType -- ^ @iface@ - the type of the requested interface
                      -> IO (Maybe Element) -- ^ the 'Element' inside @bin@ that implements @iface@, or 'Nothing'
    binGetByInterface bin iface =
        (\(Bin arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_get_by_interface argPtr1 arg2) (toBin bin) (fromIntegral iface) >>=
            maybePeek takeObject

    -- | Get an 'Iterator' over the 'Element's in @bin@.
    binIterateElements :: BinClass bin
                       => bin -- ^ @bin@ - a 'Bin'
                       -> IO (Maybe (Iterator Element)) -- ^ an 'Iterator' over the 'Element's in @bin@,
                                                        -- or 'Nothing'
    binIterateElements bin =
        (\(Bin arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_iterate_elements argPtr1) (toBin bin) >>=
            maybePeek takeIterator

    -- | Get an 'Iterator' over the 'Element's in @bin@. This
    -- iterator recurses into @bin@'s children.
    binIterateRecurse :: BinClass bin
                      => bin -- ^ @bin@ - a 'Bin'
                      -> IO (Maybe (Iterator Element)) -- ^ an 'Iterator' over the 'Element's in @bin@
                                                       -- and its descendents, or 'Nothing'
    binIterateRecurse bin =
        (\(Bin arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_iterate_recurse argPtr1) (toBin bin) >>=
            maybePeek takeIterator

    -- | Get an iterator over the 'Element's in @bin@ that have the
    -- 'ElementIsSink' flag set.
    binIterateSinks :: BinClass bin
                    => bin -- ^ @bin@ - a 'Bin'
                    -> IO (Maybe (Iterator Element)) -- ^ an 'Iterator' over the sinks in @bin@, or 'Nothing'
    binIterateSinks bin =
        (\(Bin arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_iterate_sinks argPtr1) (toBin bin) >>=
            maybePeek takeIterator

    -- | Gets an iterator for the elements in this bin in topologically
    -- sorted order. This means that the elements are returned from the
    -- most downstream elements (sinks) to the sources.
    --
    -- This function is used internally to perform state changes of the
    -- bin elements.
    binIterateSorted :: BinClass bin
                     => bin -- ^ @bin@ - a 'Bin'
                     -> IO (Maybe (Iterator Element)) -- ^ an 'Iterator' over the 'Element's in @bin@, or 'Nothing'
    binIterateSorted bin =
        (\(Bin arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_iterate_sorted argPtr1) (toBin bin) >>=
            maybePeek takeIterator

    -- | Gets an iterator for all elements in the bin that have no sink
    -- pads and have the 'ElementIsSink' flag unset.
    binIterateSources :: BinClass bin
                      => bin -- ^ @bin@ - a 'Bin'
                      -> IO (Maybe (Iterator Element)) -- ^ an 'Iterator' on elements, or 'Nothing'
    binIterateSources bin =
        (\(Bin arg1) -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_iterate_sources argPtr1) (toBin bin) >>=
            maybePeek takeIterator

    -- | Looks for all elements inside the bin that implement the given
    -- interface. You can safely case all elements to the given
    -- interface. The function recurses inside child bins.
    binIterateAllByInterface :: BinClass bin
                             => bin -- ^ @bin@ - a 'Bin'
                             -> GType -- ^ @iface@ - the interface's 'GType'
                             -> IO (Maybe (Iterator Element)) -- ^ an 'Iterator' on elements, or 'Nothing'
    binIterateAllByInterface bin iface =
        (\(Bin arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_iterate_all_by_interface argPtr1 arg2) (toBin bin) (fromIntegral iface) >>=
            maybePeek takeIterator

    -- | Recursively looks for elements with an unconnected pad of the
    -- given direction within the specified bin. Returns an unconnected
    -- pad if one is found, otherwise 'Nothing'.
    --
    -- Since 0.10.3.
    binFindUnconnectedPad :: BinClass bin
                          => bin -- ^ @bin@ - a 'Bin'
                          -> PadDirection -- ^ @direction@ - the direction of the requested 'Pad'
                          -> IO (Maybe Pad) -- ^ an unconnected 'Pad', or 'Nothing'
    binFindUnconnectedPad bin direction =
        (\(Bin arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gst_bin_find_unconnected_pad argPtr1 arg2) (toBin bin) (fromIntegral $ fromEnum direction) >>=
            maybePeek takeObject

    -- | An 'Element' has been added to the 'Bin'.
    binElementAdded :: BinClass bin
                    => Signal bin (Element -> IO ())
    binElementAdded =
        Signal $ connect_OBJECT__NONE "element-added"

    -- | An 'Element' has been removed from the 'Bin'.
    binElementRemoved :: BinClass bin
                      => Signal bin (Element -> IO ())
    binElementRemoved =
        Signal $ connect_OBJECT__NONE "element-added"

    foreign import ccall safe "gst_bin_new"
      gst_bin_new :: ((Ptr CChar) -> (IO (Ptr Element)))

    foreign import ccall safe "gst_bin_add"
      gst_bin_add :: ((Ptr Bin) -> ((Ptr Element) -> (IO CInt)))

    foreign import ccall safe "gst_bin_remove"
      gst_bin_remove :: ((Ptr Bin) -> ((Ptr Element) -> (IO CInt)))

    foreign import ccall safe "gst_bin_get_by_name"
      gst_bin_get_by_name :: ((Ptr Bin) -> ((Ptr CChar) -> (IO (Ptr Element))))

    foreign import ccall safe "gst_bin_get_by_name_recurse_up"
      gst_bin_get_by_name_recurse_up :: ((Ptr Bin) -> ((Ptr CChar) -> (IO (Ptr Element))))

    foreign import ccall safe "gst_bin_get_by_interface"
      gst_bin_get_by_interface :: ((Ptr Bin) -> (CUInt -> (IO (Ptr Element))))

    foreign import ccall safe "gst_bin_iterate_elements"
      gst_bin_iterate_elements :: ((Ptr Bin) -> (IO (Ptr PtrIterator)))

    foreign import ccall safe "gst_bin_iterate_recurse"
      gst_bin_iterate_recurse :: ((Ptr Bin) -> (IO (Ptr PtrIterator)))

    foreign import ccall safe "gst_bin_iterate_sinks"
      gst_bin_iterate_sinks :: ((Ptr Bin) -> (IO (Ptr PtrIterator)))

    foreign import ccall safe "gst_bin_iterate_sorted"
      gst_bin_iterate_sorted :: ((Ptr Bin) -> (IO (Ptr PtrIterator)))

    foreign import ccall safe "gst_bin_iterate_sources"
      gst_bin_iterate_sources :: ((Ptr Bin) -> (IO (Ptr PtrIterator)))

    foreign import ccall safe "gst_bin_iterate_all_by_interface"
      gst_bin_iterate_all_by_interface :: ((Ptr Bin) -> (CUInt -> (IO (Ptr PtrIterator))))

    foreign import ccall safe "gst_bin_find_unconnected_pad"
      gst_bin_find_unconnected_pad :: ((Ptr Bin) -> (CInt -> (IO (Ptr Pad))))