    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Graphics.UI.SDL.Mixer.Channels
    -- Copyright   :  (c) David Himmelstrup 2005
    -- License     :  BSD-like
    --
    -- Maintainer  :  lemmih@gmail.com
    -- Stability   :  provisional
    -- Portability :  portable
    --
    -----------------------------------------------------------------------------
    module Graphics.UI.SDL.Mixer.Channels
        ( allocateChannels
        , volume
        , tryPlayChannel
        , playChannel
        , tryFadeInChannel
        , fadeInChannel
        , tryFadeInChannelTimed
        , fadeInChannelTimed
        , pause
        , resume
        , haltChannel
        , expireChannel
        , fadeOutChannel
        , isChannelPlaying
        , numChannelsPlaying
        , isChannelPaused
        , numChannelsPaused
        , fadingChannel
        , getChunk
        ) where

    import Foreign(Ptr, newForeignPtr_, toBool, withForeignPtr)

    import Graphics.UI.SDL.Mixer.Types(Fading, Channel, Chunk, ChunkStruct)
    import Graphics.UI.SDL.General(unwrapInt)

    -- int Mix_AllocateChannels(int numchans)
    foreign import ccall unsafe "Mix_AllocateChannels" allocateChannels :: Int -> IO Int

    -- int Mix_Volume(int channel, int volume)
    foreign import ccall unsafe "Mix_Volume" volume :: Int -> Int -> IO Int

    tryPlayChannel :: Channel -> Chunk -> Int -> IO Int
    tryPlayChannel channel chunk loops
        = tryPlayChannelTimed channel chunk loops (-1)

    playChannel :: Channel -> Chunk -> Int -> IO Int
    playChannel channel chunk loops
        = playChannelTimed channel chunk loops (-1)

    -- int Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ticks)
    foreign import ccall unsafe "Mix_PlayChannelTimed" mixPlayChannelTimed
        :: Int -> Ptr ChunkStruct -> Int -> Int -> IO Int
    tryPlayChannelTimed :: Channel -> Chunk -> Int -> Int -> IO Int
    tryPlayChannelTimed channel chunk loops ticks
        = withForeignPtr chunk $ \chunkPtr ->
          mixPlayChannelTimed channel chunkPtr loops ticks

    playChannelTimed :: Channel -> Chunk -> Int -> Int -> IO Int
    playChannelTimed channel chunk loops ticks
        = unwrapInt (/=(-1)) "Mix_PlayChannelTimed"
                    (tryPlayChannelTimed channel chunk loops ticks)

    tryFadeInChannel :: Channel -> Chunk -> Int -> Int -> IO Int
    tryFadeInChannel channel chunk loops ms
        = tryFadeInChannelTimed channel chunk loops ms (-1)

    fadeInChannel :: Channel -> Chunk -> Int -> Int -> IO Int
    fadeInChannel channel chunk loops ms
        = fadeInChannelTimed channel chunk loops ms (-1)

    -- int Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ms, int ticks)
    foreign import ccall unsafe "Mix_FadeInChannelTimed" mixFadeInChannelTimed
        :: Int -> Ptr ChunkStruct -> Int -> Int -> Int -> IO Int
    tryFadeInChannelTimed :: Channel -> Chunk -> Int -> Int -> Int -> IO Int
    tryFadeInChannelTimed channel chunk loops ms ticks
        = withForeignPtr chunk $ \chunkPtr ->
          mixFadeInChannelTimed channel chunkPtr loops ms ticks

    fadeInChannelTimed :: Channel -> Chunk -> Int -> Int -> Int -> IO Int
    fadeInChannelTimed channel chunk loops ms ticks
        = unwrapInt (/=(-1)) "Mix_FadeInChannelTimed"
                    (tryFadeInChannelTimed channel chunk loops ms ticks)

    -- void Mix_Pause(int channel)
    foreign import ccall unsafe "Mix_Pause" pause :: Channel -> IO ()

    -- void Mix_Resume(int channel)
    foreign import ccall unsafe "Mix_Resume" resume :: Channel -> IO ()

    -- int Mix_HaltChannel(int channel)
    foreign import ccall unsafe "Mix_HaltChannel" mixHaltChannel :: Int -> IO Int
    haltChannel :: Channel -> IO ()
    haltChannel channel = mixHaltChannel channel >> return ()

    -- int Mix_ExpireChannel(int channel, int ticks)
    foreign import ccall unsafe "Mix_ExpireChannel" expireChannel :: Channel -> Int -> IO Int

    -- int Mix_FadeOutChannel(int channel, int ms)
    foreign import ccall unsafe "Mix_FadeOutChannel" fadeOutChannel :: Channel -> Int -> IO Int

    -- int Mix_Playing(int channel)
    foreign import ccall unsafe "Mix_Playing" mixPlaying :: Int -> IO Int

    isChannelPlaying :: Channel -> IO Bool
    isChannelPlaying = fmap toBool . mixPlaying

    numChannelsPlaying :: IO Int
    numChannelsPlaying = mixPlaying (-1)

    -- int Mix_Paused(int channel)
    foreign import ccall unsafe "Mix_Paused" mixPaused :: Int -> IO Int

    isChannelPaused :: Channel -> IO Bool
    isChannelPaused = fmap toBool . mixPaused

    numChannelsPaused :: IO Int
    numChannelsPaused = mixPaused (-1)

    -- Mix_Fading Mix_FadingChannel(int which)
    foreign import ccall unsafe "Mix_FadingChannel" mixFadingChannel :: Int -> IO Int
    fadingChannel :: Channel -> IO Fading
    fadingChannel = fmap toEnum . mixFadingChannel

    -- Mix_Chunk *Mix_GetChunk(int channel)
    foreign import ccall unsafe "Mix_GetChunk" mixGetChunk :: Int -> IO (Ptr ChunkStruct)
    getChunk :: Channel -> IO Chunk
    getChunk ch = newForeignPtr_ =<< mixGetChunk ch