gstreamer-0.11.0: Media/Streaming/GStreamer/Core/Bin.chs
{-# LANGUAGE CPP #-}
-- 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://www.gnu.org/licenses/>.
--
-- 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#}
{#import Media.Streaming.GStreamer.Core.Signals#}
{# context lib = "gstreamer" prefix = "gst" #}
-- | 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 {# call 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 $ {# call bin_add #} (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 $ {# call bin_remove #} (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 ({# call bin_get_by_name #} (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 ({# call bin_get_by_name_recurse_up #} $ 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 =
{# call bin_get_by_interface #} (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 =
{# call bin_iterate_elements #} (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 =
{# call bin_iterate_recurse #} (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 =
{# call bin_iterate_sinks #} (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 =
{# call bin_iterate_sorted #} (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 =
{# call bin_iterate_sources #} (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 =
{# call bin_iterate_all_by_interface #} (toBin bin) (fromIntegral iface) >>=
maybePeek takeIterator
#if GST_CHECK_VERSION (0, 10, 3)
-- | 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 =
{# call bin_find_unconnected_pad #} (toBin bin) (fromIntegral $ fromEnum direction) >>=
maybePeek takeObject
#endif
-- | 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"