{-# LINE 2 "./Graphics/UI/Gtk/Gdk/PixbufAnimation.chs" #-}
-- -*-haskell-*-
-- GIMP Toolkit (GTK) Pixbuf Animation
--
-- Author : Matthew Arsenault
--
-- Created: 14 November 2009
--
-- Copyright (C) 2009 Matthew Arsenault
--
-- 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 2.1 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.
--
-- |
-- Maintainer : gtk2hs-users@lists.sourceforge.net
-- Stability : provisional
-- Portability : portable (depends on GHC)
--
module Graphics.UI.Gtk.Gdk.PixbufAnimation (
-- * Class Hierarchy
-- |
-- @
-- | 'GObject'
-- | +----'PixbufAnimation'
-- | +----'PixbufSimpleAnim'
-- @

-- * Types
  PixbufAnimation,
  PixbufAnimationClass,
  castToPixbufAnimation, gTypePixbufAnimation,
  toPixbufAnimation,

  PixbufAnimationIter,
  PixbufAnimationIterClass,
  castToPixbufAnimationIter, gTypePixbufAnimationIter,
  toPixbufAnimationIter,

  PixbufSimpleAnim,
  PixbufSimpleAnimClass,
  castToPixbufSimpleAnim, gTypePixbufSimpleAnim,
  toPixbufSimpleAnim,

-- * Constructors
  pixbufAnimationNewFromFile,

  pixbufSimpleAnimNew,


-- * Methods
  pixbufAnimationGetWidth,
  pixbufAnimationGetHeight,
  pixbufAnimationGetIter,
  pixbufAnimationIsStaticImage,
  pixbufAnimationGetStaticImage,
  pixbufAnimationIterAdvance,
  pixbufAnimationIterGetDelayTime,
  pixbufAnimationIterOnCurrentlyLoadingFrame,
  pixbufAnimationIterGetPixbuf,

  pixbufSimpleAnimAddFrame,



  pixbufSimpleAnimSetLoop,
  pixbufSimpleAnimGetLoop

  ) where

import Control.Monad (liftM)
import System.Glib.FFI
import System.Glib.UTFString
import System.Glib.GDateTime
import System.Glib.GObject
import Graphics.UI.Gtk.Types
{-# LINE 83 "./Graphics/UI/Gtk/Gdk/PixbufAnimation.chs" #-}
import System.Glib.GError (GError(..), GErrorClass(..), GErrorDomain,
    propagateGError)
import Graphics.UI.Gtk.Gdk.Pixbuf
{-# LINE 86 "./Graphics/UI/Gtk/Gdk/PixbufAnimation.chs" #-}


{-# LINE 88 "./Graphics/UI/Gtk/Gdk/PixbufAnimation.chs" #-}


--CHECKME: Domain error doc, GFileError ???
-- | Creates a new animation by loading it from a file. The file
-- format is detected automatically. If the file's format does not
-- support multi-frame images, then an animation with a single frame
-- will be created. Possible errors are in the 'PixbufError' and
-- 'GFileError' domains.
--
-- Any of several error conditions may occur: the file could not be
-- opened, there was no loader for the file's format, there was not
-- enough memory to allocate the image buffer, or the image file
-- contained invalid data.
--
-- * If an error occurs, the function will throw an exception that can
-- be caught using e.g. 'System.Glib.GError.catchGErrorJust' and one of the
-- error codes in 'PixbufError' or 'GFileError'
--
pixbufAnimationNewFromFile :: FilePath -- ^ Name of file to load, in the GLib file name encoding
                           -> IO PixbufAnimation -- ^ A newly-created animation
pixbufAnimationNewFromFile fname =
  wrapNewGObject mkPixbufAnimation $
  propagateGError $ \errPtrPtr ->
     withUTFString fname $ \strPtr ->



     gdk_pixbuf_animation_new_from_file strPtr errPtrPtr


-- | Queries the width of the bounding box of a pixbuf animation.
pixbufAnimationGetWidth :: PixbufAnimation -- ^ An animation.
                        -> IO Int -- ^ Width of the bounding box of the animation.
pixbufAnimationGetWidth self = liftM fromIntegral $ (\(PixbufAnimation arg1) -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_animation_get_width argPtr1) self

-- | Queries the height of the bounding box of a pixbuf animation.
pixbufAnimationGetHeight :: PixbufAnimation -- ^ An animation.
                         -> IO Int -- ^ Height of the bounding box of the animation.
pixbufAnimationGetHeight self = liftM fromIntegral $ (\(PixbufAnimation arg1) -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_animation_get_height argPtr1) self


-- | Get an iterator for displaying an animation. The iterator
-- provides the frames that should be displayed at a given time. The
-- start time would normally come from 'gGetCurrentTime', and marks
-- the beginning of animation playback. After creating an iterator,
-- you should immediately display the pixbuf returned by
-- 'pixbufAnimationIterGetPixbuf'. Then, you should install a
-- timeout (with 'timeoutAdd') or by some other mechanism ensure
-- that you'll update the image after
-- 'pixbufAnimationIterGetDelayTime' milliseconds. Each time the
-- image is updated, you should reinstall the timeout with the new,
-- possibly-changed delay time.
--
-- As a shortcut, if start_time is @Nothing@, the result of
-- 'gGetCurrentTime' will be used automatically.
--
-- To update the image (i.e. possibly change the result of
-- 'pixbufAnimationIterGetPixbuf' to a new frame of the animation),
-- call 'pixbufAnimationIterAdvance'.
--
-- If you're using 'PixbufLoader', in addition to updating the image
-- after the delay time, you should also update it whenever you
-- receive the area_updated signal and
-- 'pixbufAnimationIterOnCurrentlyLoadingFrame' returns @True@. In
-- this case, the frame currently being fed into the loader has
-- received new data, so needs to be refreshed. The delay time for a
-- frame may also be modified after an area_updated signal, for
-- example if the delay time for a frame is encoded in the data after
-- the frame itself. So your timeout should be reinstalled after any
-- area_updated signal.
--
-- A delay time of -1 is possible, indicating "infinite."
--
pixbufAnimationGetIter :: PixbufAnimation -- ^ a 'PixbufAnimation'
                       -> Maybe GTimeVal -- ^ time when the animation starts playing
                       -> IO PixbufAnimationIter -- ^ an iterator to move over the animation
pixbufAnimationGetIter self tv = maybeWith with tv $ \stPtr ->
                                 wrapNewGObject mkPixbufAnimationIter $
                                   (\(PixbufAnimation arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_animation_get_iter argPtr1 arg2) self (castPtr stPtr)



-- | If you load a file with 'pixbufAnimationNewFromFile' and it turns
-- out to be a plain, unanimated image, then this function will
-- return @True@. Use 'pixbufAnimationGetStaticImage' to retrieve
-- the image.
--
pixbufAnimationIsStaticImage :: PixbufAnimation
                             -> IO Bool -- ^ (!(0)) if the "animation" was really just an image
pixbufAnimationIsStaticImage self = liftM toBool $ (\(PixbufAnimation arg1) -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_animation_is_static_image argPtr1) self


-- | If an animation is really just a plain image (has only one
-- frame), this function returns that image. If the animation is an
-- animation, this function returns a reasonable thing to display as
-- a static unanimated image, which might be the first frame, or
-- something more sophisticated. If an animation hasn't loaded any
-- frames yet, this function will return @Nothing@.
--
pixbufAnimationGetStaticImage :: PixbufAnimation
                              -> IO (Maybe Pixbuf) -- ^ unanimated image representing the animation
pixbufAnimationGetStaticImage self =
  maybeNull (makeNewGObject mkPixbuf) $ (\(PixbufAnimation arg1) -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_animation_get_static_image argPtr1) self



-- | Possibly advances an animation to a new frame. Chooses the frame
-- based on the start time passed to 'pixbufAnimationGetIter'.
--
-- current_time would normally come from 'gGetCurrentTime', and must
-- be greater than or equal to the time passed to
-- 'pixbufAnimationGetIter', and must increase or remain unchanged
-- each time 'pixbufAnimationIterGetPixbuf' is called. That is, you
-- can't go backward in time; animations only play forward.
--
-- As a shortcut, pass @Nothing@ for the current time and
-- 'gGetCurrentTime' will be invoked on your behalf. So you only need
-- to explicitly pass current_time if you're doing something odd like
-- playing the animation at double speed.
--
-- If this function returns @False@, there's no need to update the
-- animation display, assuming the display had been rendered prior to
-- advancing; if @True@, you need to call 'animationIterGetPixbuf' and
-- update the display with the new pixbuf.
--
pixbufAnimationIterAdvance :: PixbufAnimationIter -- ^ A 'PixbufAnimationIter'
                           -> Maybe GTimeVal -- ^ current time
                           -> IO Bool -- ^ @True@ if the image may need updating
pixbufAnimationIterAdvance iter currentTime = liftM toBool $ maybeWith with currentTime $ \tvPtr ->
                                                (\(PixbufAnimationIter arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_animation_iter_advance argPtr1 arg2) iter (castPtr tvPtr)


-- | Gets the number of milliseconds the current pixbuf should be
-- displayed, or -1 if the current pixbuf should be displayed
-- forever. 'timeoutAdd' conveniently takes a timeout in
-- milliseconds, so you can use a timeout to schedule the next
-- update.
--
pixbufAnimationIterGetDelayTime :: PixbufAnimationIter -- ^ an animation iterator
                                -> IO Int -- ^ delay time in milliseconds (thousandths of a second)
pixbufAnimationIterGetDelayTime self = liftM fromIntegral $
  (\(PixbufAnimationIter arg1) -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_animation_iter_get_delay_time argPtr1) self


-- | Used to determine how to respond to the area_updated signal on
-- 'PixbufLoader' when loading an animation. area_updated is emitted
-- for an area of the frame currently streaming in to the loader. So
-- if you're on the currently loading frame, you need to redraw the
-- screen for the updated area.
--
pixbufAnimationIterOnCurrentlyLoadingFrame :: PixbufAnimationIter
                                           -> IO Bool -- ^ @True@ if the frame we're on is partially loaded, or the last frame
pixbufAnimationIterOnCurrentlyLoadingFrame iter = liftM toBool $
  (\(PixbufAnimationIter arg1) -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_animation_iter_on_currently_loading_frame argPtr1) iter

--CHECKME: referencing, usage of constructNewGObject
-- | Gets the current pixbuf which should be displayed; the pixbuf will
-- be the same size as the animation itself
-- ('pixbufAnimationGetWidth', 'pixbufAnimationGetHeight'). This
-- pixbuf should be displayed for 'pixbufAnimationIterGetDelayTime'
-- milliseconds. The caller of this function does not own a reference
-- to the returned pixbuf; the returned pixbuf will become invalid
-- when the iterator advances to the next frame, which may happen
-- anytime you call 'pixbufAnimationIterAdvance'. Copy the pixbuf to
-- keep it (don't just add a reference), as it may get recycled as you
-- advance the iterator.
--
pixbufAnimationIterGetPixbuf :: PixbufAnimationIter -- ^ an animation iterator
                                -> IO Pixbuf -- ^ the pixbuf to be displayed
pixbufAnimationIterGetPixbuf iter = makeNewGObject mkPixbuf $
   (\(PixbufAnimationIter arg1) -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_animation_iter_get_pixbuf argPtr1) iter



-- | Creates a new, empty animation.
--
-- * Available since Gtk+ version 2.8
--
pixbufSimpleAnimNew :: Int -- ^ the width of the animation
                    -> Int -- ^ the height of the animation
                    -> Float -- ^ the speed of the animation, in frames per second
                    -> IO PixbufSimpleAnim -- ^ a newly allocated 'PixbufSimpleAnim'
pixbufSimpleAnimNew width height rate = wrapNewGObject mkPixbufSimpleAnim $
  gdk_pixbuf_simple_anim_new (fromIntegral width) (fromIntegral height) (realToFrac rate)


-- | Adds a new frame to animation. The pixbuf must have the
-- dimensions specified when the animation was constructed.
--
-- * Available since Gtk+ version 2.8
--
pixbufSimpleAnimAddFrame :: PixbufSimpleAnim -- ^ a 'PixbufSimpleAnim'
                         -> Pixbuf -- ^ the pixbuf to add
                         -> IO ()
pixbufSimpleAnimAddFrame psa pb = (\(PixbufSimpleAnim arg1) (Pixbuf arg2) -> withForeignPtr arg1 $ \argPtr1 ->withForeignPtr arg2 $ \argPtr2 ->gdk_pixbuf_simple_anim_add_frame argPtr1 argPtr2) psa pb





-- | Sets whether animation should loop indefinitely when it reaches
-- the end.
--
-- * Available since Gtk+ version 2.18
--
pixbufSimpleAnimSetLoop :: PixbufSimpleAnim -- ^ a 'PixbufSimpleAnim'
                           -> Bool -- ^ whether to loop the animation
                           -> IO ()
pixbufSimpleAnimSetLoop animation loop = (\(PixbufSimpleAnim arg1) arg2 -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_simple_anim_set_loop argPtr1 arg2) animation (fromBool loop)


-- | Gets whether animation should loop indefinitely when it reaches
-- the end.
--
-- * Available since Gtk+ version 2.18
--
pixbufSimpleAnimGetLoop :: PixbufSimpleAnim -- ^ a 'PixbufSimpleAnim'
                           -> IO Bool -- ^ @True@ if the animation loops forever, @False@ otherwise
pixbufSimpleAnimGetLoop animation = liftM toBool $ (\(PixbufSimpleAnim arg1) -> withForeignPtr arg1 $ \argPtr1 ->gdk_pixbuf_simple_anim_get_loop argPtr1) animation

foreign import ccall unsafe "gdk_pixbuf_animation_new_from_file"
  gdk_pixbuf_animation_new_from_file :: ((Ptr CChar) -> ((Ptr (Ptr ())) -> (IO (Ptr PixbufAnimation))))

foreign import ccall unsafe "gdk_pixbuf_animation_get_width"
  gdk_pixbuf_animation_get_width :: ((Ptr PixbufAnimation) -> (IO CInt))

foreign import ccall unsafe "gdk_pixbuf_animation_get_height"
  gdk_pixbuf_animation_get_height :: ((Ptr PixbufAnimation) -> (IO CInt))

foreign import ccall unsafe "gdk_pixbuf_animation_get_iter"
  gdk_pixbuf_animation_get_iter :: ((Ptr PixbufAnimation) -> ((Ptr ()) -> (IO (Ptr PixbufAnimationIter))))

foreign import ccall unsafe "gdk_pixbuf_animation_is_static_image"
  gdk_pixbuf_animation_is_static_image :: ((Ptr PixbufAnimation) -> (IO CInt))

foreign import ccall unsafe "gdk_pixbuf_animation_get_static_image"
  gdk_pixbuf_animation_get_static_image :: ((Ptr PixbufAnimation) -> (IO (Ptr Pixbuf)))

foreign import ccall unsafe "gdk_pixbuf_animation_iter_advance"
  gdk_pixbuf_animation_iter_advance :: ((Ptr PixbufAnimationIter) -> ((Ptr ()) -> (IO CInt)))

foreign import ccall unsafe "gdk_pixbuf_animation_iter_get_delay_time"
  gdk_pixbuf_animation_iter_get_delay_time :: ((Ptr PixbufAnimationIter) -> (IO CInt))

foreign import ccall unsafe "gdk_pixbuf_animation_iter_on_currently_loading_frame"
  gdk_pixbuf_animation_iter_on_currently_loading_frame :: ((Ptr PixbufAnimationIter) -> (IO CInt))

foreign import ccall unsafe "gdk_pixbuf_animation_iter_get_pixbuf"
  gdk_pixbuf_animation_iter_get_pixbuf :: ((Ptr PixbufAnimationIter) -> (IO (Ptr Pixbuf)))

foreign import ccall unsafe "gdk_pixbuf_simple_anim_new"
  gdk_pixbuf_simple_anim_new :: (CInt -> (CInt -> (CFloat -> (IO (Ptr PixbufSimpleAnim)))))

foreign import ccall unsafe "gdk_pixbuf_simple_anim_add_frame"
  gdk_pixbuf_simple_anim_add_frame :: ((Ptr PixbufSimpleAnim) -> ((Ptr Pixbuf) -> (IO ())))

foreign import ccall unsafe "gdk_pixbuf_simple_anim_set_loop"
  gdk_pixbuf_simple_anim_set_loop :: ((Ptr PixbufSimpleAnim) -> (CInt -> (IO ())))

foreign import ccall unsafe "gdk_pixbuf_simple_anim_get_loop"
  gdk_pixbuf_simple_anim_get_loop :: ((Ptr PixbufSimpleAnim) -> (IO CInt))