Pick the right function to load a Pixbuf on Windows.

{-# LANGUAGE CPP #-}
-- -*-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,
#if GTK_CHECK_VERSION(2,8,0)
  pixbufSimpleAnimNew,
#endif

-- * Methods
  pixbufAnimationGetWidth,
  pixbufAnimationGetHeight,
  pixbufAnimationGetIter,
  pixbufAnimationIsStaticImage,
  pixbufAnimationGetStaticImage,
  pixbufAnimationIterAdvance,
  pixbufAnimationIterGetDelayTime,
  pixbufAnimationIterOnCurrentlyLoadingFrame,
  pixbufAnimationIterGetPixbuf,
#if GTK_CHECK_VERSION(2,8,0)
  pixbufSimpleAnimAddFrame,
#endif

#if GTK_CHECK_VERSION(2,18,0)
  pixbufSimpleAnimSetLoop,
  pixbufSimpleAnimGetLoop
#endif
  ) 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#}
import System.Glib.GError	(GError(..), GErrorClass(..), GErrorDomain,
				propagateGError)
{# import Graphics.UI.Gtk.Gdk.Pixbuf #}

{# context prefix="gdk" #}

--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 =
  constructNewGObject mkPixbufAnimation $
  propagateGError $ \errPtrPtr ->
     withUTFString fname $ \strPtr ->
#if defined (WIN32) && GTK_CHECK_VERSION(2,6,5)
     {#call unsafe pixbuf_animation_new_from_file_utf8#} strPtr errPtrPtr
#else
     {#call unsafe pixbuf_animation_new_from_file#} strPtr errPtrPtr
#endif

-- | 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 $ {#call unsafe pixbuf_animation_get_width#} 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 $ {#call unsafe pixbuf_animation_get_height#} 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 ->
                                 constructNewGObject mkPixbufAnimationIter $
                                   {#call unsafe pixbuf_animation_get_iter#} 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          -- ^ TRUE if the "animation" was really just an image
pixbufAnimationIsStaticImage self = liftM toBool $ {#call unsafe pixbuf_animation_is_static_image#} 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 (constructNewGObject mkPixbuf) $ {#call unsafe pixbuf_animation_get_static_image#} 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 ->
                                                {# call unsafe pixbuf_animation_iter_advance #} 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 $
  {#call unsafe pixbuf_animation_iter_get_delay_time#} 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 $
  {# call unsafe pixbuf_animation_iter_on_currently_loading_frame #} 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 = constructNewGObject mkPixbuf $
   {# call unsafe pixbuf_animation_iter_get_pixbuf #} iter

#if GTK_CHECK_VERSION(2,8,0)
-- | 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 = constructNewGObject mkPixbufSimpleAnim $
  {#call unsafe 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 = {#call unsafe pixbuf_simple_anim_add_frame#} psa pb

#endif

#if GTK_CHECK_VERSION(2,18,0)

-- | 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 = {#call unsafe pixbuf_simple_anim_set_loop#} 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 $ {#call unsafe pixbuf_simple_anim_get_loop#} animation

#endif

{-# LANGUAGE CPP #-}
-- -*-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,
#if GTK_CHECK_VERSION(2,8,0)
  pixbufSimpleAnimNew,
#endif

-- * Methods
  pixbufAnimationGetWidth,
  pixbufAnimationGetHeight,
  pixbufAnimationGetIter,
  pixbufAnimationIsStaticImage,
  pixbufAnimationGetStaticImage,
  pixbufAnimationIterAdvance,
  pixbufAnimationIterGetDelayTime,
  pixbufAnimationIterOnCurrentlyLoadingFrame,
  pixbufAnimationIterGetPixbuf,
#if GTK_CHECK_VERSION(2,8,0)
  pixbufSimpleAnimAddFrame,
#endif

#if GTK_CHECK_VERSION(2,18,0)
  pixbufSimpleAnimSetLoop,
  pixbufSimpleAnimGetLoop
#endif
  ) 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#}
import System.Glib.GError	(GError(..), GErrorClass(..), GErrorDomain,
				propagateGError)
{# import Graphics.UI.Gtk.Gdk.Pixbuf #}

{# context prefix="gdk" #}

--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 =
  constructNewGObject mkPixbufAnimation $
  propagateGError $ \errPtrPtr ->
     withUTFString fname $ \strPtr ->
     {#call unsafe 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 $ {#call unsafe pixbuf_animation_get_width#} 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 $ {#call unsafe pixbuf_animation_get_height#} 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 ->
                                 constructNewGObject mkPixbufAnimationIter $
                                   {#call unsafe pixbuf_animation_get_iter#} 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          -- ^ TRUE if the "animation" was really just an image
pixbufAnimationIsStaticImage self = liftM toBool $ {#call unsafe pixbuf_animation_is_static_image#} 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 (constructNewGObject mkPixbuf) $ {#call unsafe pixbuf_animation_get_static_image#} 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 ->
                                                {# call unsafe pixbuf_animation_iter_advance #} 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 $
  {#call unsafe pixbuf_animation_iter_get_delay_time#} 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 $
  {# call unsafe pixbuf_animation_iter_on_currently_loading_frame #} 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 = constructNewGObject mkPixbuf $
   {# call unsafe pixbuf_animation_iter_get_pixbuf #} iter

#if GTK_CHECK_VERSION(2,8,0)
-- | 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 = constructNewGObject mkPixbufSimpleAnim $
  {#call unsafe 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 = {#call unsafe pixbuf_simple_anim_add_frame#} psa pb

#endif

#if GTK_CHECK_VERSION(2,18,0)

-- | 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 = {#call unsafe pixbuf_simple_anim_set_loop#} 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 $ {#call unsafe pixbuf_simple_anim_get_loop#} animation

#endif


give haskell-style names to texture data types

Ignore-this: 2b4c592d38359825c1d116ff145955c8

darcs-hash:20100610001247-dcabc-d0e1878c79bf1ba9c8b28084093ccd9e04889f9c.gz

{-# LANGUAGE ForeignFunctionInterface #-}
--------------------------------------------------------------------------------
-- |
-- Module    : Foreign.CUDA.Driver.Texture
-- Copyright : (c) [2009..2010] Trevor L. McDonell
-- License   : BSD
--
-- Texture management for low-level driver interface
--
--------------------------------------------------------------------------------

module Foreign.CUDA.Driver.Texture
  (
    Texture(Texture), AddressMode(..), FilterMode(..), Format(..),
    create, destroy,
    getPtr, getAddressMode, getFilterMode, getFormat,
    setPtr, setAddressMode, setFilterMode, setFormat
  )
  where

#include <cuda.h>
{# context lib="cuda" #}

-- Friends
import Foreign.CUDA.Ptr
import Foreign.CUDA.Driver.Error
import Foreign.CUDA.Driver.Marshal
import Foreign.CUDA.Internal.C2HS

-- System
import Foreign
import Foreign.C
import Control.Monad

--------------------------------------------------------------------------------
-- Data Types
--------------------------------------------------------------------------------

-- |A texture reference
--
newtype Texture = Texture { useTexture :: {# type CUtexref #}}

-- |Texture reference addressing modes
--
{# enum CUaddress_mode as AddressMode
  { underscoreToCase }
  with prefix="CU_TR_ADDRESS_MODE" deriving (Eq, Show) #}

-- |Texture reference filtering mode
--
{# enum CUfilter_mode as FilterMode
  { underscoreToCase }
  with prefix="CU_TR_FILTER_MODE" deriving (Eq, Show) #}

-- |Texture data formats
--
{# enum CUarray_format as Format
  { underscoreToCase
  , UNSIGNED_INT8  as Word8
  , UNSIGNED_INT16 as Word16
  , UNSIGNED_INT32 as Word32
  , SIGNED_INT8    as Int8
  , SIGNED_INT16   as Int16
  , SIGNED_INT32   as Int32 }
  with prefix="CU_AD_FORMAT" deriving (Eq, Show) #}

--------------------------------------------------------------------------------
-- Texture management
--------------------------------------------------------------------------------

-- |Create a new texture reference. Once created, the application must call
-- 'setPtr' to associate the reference with allocated memory. Other texture
-- reference functions are used to specify the format and interpretation to be
-- used when the memory is read through this reference.
--
create :: IO Texture
create = resultIfOk =<< cuTexRefCreate

{# fun unsafe cuTexRefCreate
  { alloca- `Texture' peekTex* } -> `Status' cToEnum #}

-- |Destroy a texture reference
--
destroy :: Texture -> IO ()
destroy tex = nothingIfOk =<< cuTexRefDestroy tex

{# fun unsafe cuTexRefDestroy
  { useTexture `Texture' } -> `Status' cToEnum #}

-- |Get the address associated with a texture reference
--
getPtr :: Texture -> IO (DevicePtr a)
getPtr tex = resultIfOk =<< cuTexRefGetAddress tex

{# fun unsafe cuTexRefGetAddress
  { alloca-    `DevicePtr a' peekDevPtr*
  , useTexture `Texture'                 } -> `Status' cToEnum #}

-- |Get the addressing mode used by a texture reference, corresponding to the
-- given dimension (currently the only supported dimension values are 0 or 1).
--
getAddressMode :: Texture -> Int -> IO AddressMode
getAddressMode tex dim = resultIfOk =<< cuTexRefGetAddressMode tex dim

{# fun unsafe cuTexRefGetAddressMode
  { alloca-    `AddressMode' peekEnum*
  , useTexture `Texture'
  ,            `Int'                  } -> `Status' cToEnum #}

-- |Get the filtering mode used by a texture reference
--
getFilterMode :: Texture -> IO FilterMode
getFilterMode tex = resultIfOk =<< cuTexRefGetFilterMode tex

{# fun unsafe cuTexRefGetFilterMode
  { alloca-    `FilterMode' peekEnum*
  , useTexture `Texture'              } -> `Status' cToEnum #}

-- |Get the data format and number of channel components of the bound texture
--
getFormat :: Texture -> IO (Format, Int)
getFormat tex = do
  (status,fmt,dim) <- cuTexRefGetFormat tex
  resultIfOk (status,(fmt,dim))

{# fun unsafe cuTexRefGetFormat
  { alloca-    `Format'  peekEnum*
  , alloca-    `Int'     peekIntConv*
  , useTexture `Texture'              } -> `Status' cToEnum #}

-- |Bind a linear array address of the given size (bytes) as a texture
-- reference. Any previously bound references are unbound.
--
setPtr :: Texture -> DevicePtr a -> Int -> IO ()
setPtr tex dptr bytes = nothingIfOk =<< cuTexRefSetAddress tex dptr bytes

{# fun unsafe cuTexRefSetAddress
  { alloca-         `Int'
  , useTexture      `Texture'
  , useDeviceHandle `DevicePtr a'
  ,                 `Int'         } -> `Status' cToEnum #}

-- |Specify the addressing mode for the given dimension of a texture reference
--
setAddressMode :: Texture -> Int -> AddressMode -> IO ()
setAddressMode tex dim mode = nothingIfOk =<< cuTexRefSetAddressMode tex dim mode

{# fun unsafe cuTexRefSetAddressMode
  { useTexture `Texture'
  ,            `Int'
  , cFromEnum  `AddressMode' } -> `Status' cToEnum #}

-- |Specify the filtering mode to be used when reading memory through a texture
-- reference
--
setFilterMode :: Texture -> FilterMode -> IO ()
setFilterMode tex mode = nothingIfOk =<< cuTexRefSetFilterMode tex mode

{# fun unsafe cuTexRefSetFilterMode
  { useTexture `Texture'
  , cFromEnum  `FilterMode' } -> `Status' cToEnum #}

-- |Specify the format of the data to be read by the texture reference
--
setFormat :: Texture -> Format -> Int -> IO ()
setFormat tex fmt dim = nothingIfOk =<< cuTexRefSetFormat tex fmt dim

{# fun unsafe cuTexRefSetFormat
  { useTexture `Texture'
  , cFromEnum  `Format'
  ,            `Int'     } -> `Status' cToEnum #}

--------------------------------------------------------------------------------
-- Internal
--------------------------------------------------------------------------------

peekTex :: Ptr {# type CUtexref #} -> IO Texture
peekTex = liftM Texture . peek

{-# LANGUAGE ForeignFunctionInterface #-}
--------------------------------------------------------------------------------
-- |
-- Module    : Foreign.CUDA.Driver.Texture
-- Copyright : (c) [2009..2010] Trevor L. McDonell
-- License   : BSD
--
-- Texture management for low-level driver interface
--
--------------------------------------------------------------------------------

module Foreign.CUDA.Driver.Texture
  (
    Texture(Texture), AddressMode(..), FilterMode(..), Format(..),
    create, destroy,
    getPtr, getAddressMode, getFilterMode, getFormat,
    setPtr, setAddressMode, setFilterMode, setFormat
  )
  where

#include <cuda.h>
{# context lib="cuda" #}

-- Friends
import Foreign.CUDA.Ptr
import Foreign.CUDA.Driver.Error
import Foreign.CUDA.Driver.Marshal
import Foreign.CUDA.Internal.C2HS

-- System
import Foreign
import Foreign.C
import Control.Monad

--------------------------------------------------------------------------------
-- Data Types
--------------------------------------------------------------------------------

-- |A texture reference
--
newtype Texture = Texture { useTexture :: {# type CUtexref #}}

-- |Texture reference addressing modes
--
{# enum CUaddress_mode as AddressMode
  { underscoreToCase }
  with prefix="CU_TR_ADDRESS_MODE" deriving (Eq, Show) #}

-- |Texture reference filtering mode
--
{# enum CUfilter_mode as FilterMode
  { underscoreToCase }
  with prefix="CU_TR_FILTER_MODE" deriving (Eq, Show) #}

-- |Texture data formats
--
{# enum CUarray_format as Format
  { underscoreToCase }
  with prefix="CU_AD_FORMAT" deriving (Eq, Show) #}

--------------------------------------------------------------------------------
-- Texture management
--------------------------------------------------------------------------------

-- |Create a new texture reference. Once created, the application must call
-- 'setPtr' to associate the reference with allocated memory. Other texture
-- reference functions are used to specify the format and interpretation to be
-- used when the memory is read through this reference.
--
create :: IO Texture
create = resultIfOk =<< cuTexRefCreate

{# fun unsafe cuTexRefCreate
  { alloca- `Texture' peekTex* } -> `Status' cToEnum #}

-- |Destroy a texture reference
--
destroy :: Texture -> IO ()
destroy tex = nothingIfOk =<< cuTexRefDestroy tex

{# fun unsafe cuTexRefDestroy
  { useTexture `Texture' } -> `Status' cToEnum #}

-- |Get the address associated with a texture reference
--
getPtr :: Texture -> IO (DevicePtr a)
getPtr tex = resultIfOk =<< cuTexRefGetAddress tex

{# fun unsafe cuTexRefGetAddress
  { alloca-    `DevicePtr a' peekDevPtr*
  , useTexture `Texture'                 } -> `Status' cToEnum #}

-- |Get the addressing mode used by a texture reference, corresponding to the
-- given dimension (currently the only supported dimension values are 0 or 1).
--
getAddressMode :: Texture -> Int -> IO AddressMode
getAddressMode tex dim = resultIfOk =<< cuTexRefGetAddressMode tex dim

{# fun unsafe cuTexRefGetAddressMode
  { alloca-    `AddressMode' peekEnum*
  , useTexture `Texture'
  ,            `Int'                  } -> `Status' cToEnum #}

-- |Get the filtering mode used by a texture reference
--
getFilterMode :: Texture -> IO FilterMode
getFilterMode tex = resultIfOk =<< cuTexRefGetFilterMode tex

{# fun unsafe cuTexRefGetFilterMode
  { alloca-    `FilterMode' peekEnum*
  , useTexture `Texture'              } -> `Status' cToEnum #}

-- |Get the data format and number of channel components of the bound texture
--
getFormat :: Texture -> IO (Format, Int)
getFormat tex = do
  (status,fmt,dim) <- cuTexRefGetFormat tex
  resultIfOk (status,(fmt,dim))

{# fun unsafe cuTexRefGetFormat
  { alloca-    `Format'  peekEnum*
  , alloca-    `Int'     peekIntConv*
  , useTexture `Texture'              } -> `Status' cToEnum #}

-- |Bind a linear array address of the given size (bytes) as a texture
-- reference. Any previously bound references are unbound.
--
setPtr :: Texture -> DevicePtr a -> Int -> IO ()
setPtr tex dptr bytes = nothingIfOk =<< cuTexRefSetAddress tex dptr bytes

{# fun unsafe cuTexRefSetAddress
  { alloca-         `Int'
  , useTexture      `Texture'
  , useDeviceHandle `DevicePtr a'
  ,                 `Int'         } -> `Status' cToEnum #}

-- |Specify the addressing mode for the given dimension of a texture reference
--
setAddressMode :: Texture -> Int -> AddressMode -> IO ()
setAddressMode tex dim mode = nothingIfOk =<< cuTexRefSetAddressMode tex dim mode

{# fun unsafe cuTexRefSetAddressMode
  { useTexture `Texture'
  ,            `Int'
  , cFromEnum  `AddressMode' } -> `Status' cToEnum #}

-- |Specify the filtering mode to be used when reading memory through a texture
-- reference
--
setFilterMode :: Texture -> FilterMode -> IO ()
setFilterMode tex mode = nothingIfOk =<< cuTexRefSetFilterMode tex mode

{# fun unsafe cuTexRefSetFilterMode
  { useTexture `Texture'
  , cFromEnum  `FilterMode' } -> `Status' cToEnum #}

-- |Specify the format of the data to be read by the texture reference
--
setFormat :: Texture -> Format -> Int -> IO ()
setFormat tex fmt dim = nothingIfOk =<< cuTexRefSetFormat tex fmt dim

{# fun unsafe cuTexRefSetFormat
  { useTexture `Texture'
  , cFromEnum  `Format'
  ,            `Int'     } -> `Status' cToEnum #}

--------------------------------------------------------------------------------
-- Internal
--------------------------------------------------------------------------------

peekTex :: Ptr {# type CUtexref #} -> IO Texture
peekTex = liftM Texture . peek