{-# LINE 1 "Graphics/UI/SDL/Joystick.hsc" #-}


{-# LINE 5 "Graphics/UI/SDL/Joystick.hsc" #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Graphics.UI.SDL.Joystick
-- Copyright   :  (c) David Himmelstrup 2005
-- License     :  BSD-like
--
-- Maintainer  :  lemmih@gmail.com
-- Stability   :  provisional
-- Portability :  portable
--
-----------------------------------------------------------------------------
module Graphics.UI.SDL.Joystick
    ( countAvailable
    , tryName
    , name
    , tryOpen
    , open
    , opened
    , index
    , axesAvailable
    , ballsAvailable
    , hatsAvailable
    , buttonsAvailable
    , update
    , getAxis
    , getHat
    , getButton
    , getBall
    , close
    ) where

import Foreign (Int16, Word8, Ptr, FunPtr, Storable(peek),
                finalizeForeignPtr, toBool, maybePeek, alloca, withForeignPtr, newForeignPtr)
import Foreign.C (peekCString, CString)
import System.IO.Unsafe (unsafePerformIO)

import Graphics.UI.SDL.General (unwrapMaybe)
import Graphics.UI.SDL.Utilities (fromBitmask)
import Graphics.UI.SDL.Types (Hat, Joystick, JoystickStruct)

type JoystickIndex = Int

--int SDL_NumJoysticks(void);
-- | Counts the number of joysticks attached to the system.
foreign import ccall unsafe "SDL_NumJoysticks" countAvailable :: IO Int

-- const char *SDL_JoystickName(int index);
foreign import ccall unsafe "SDL_JoystickName" sdlJoystickName :: JoystickIndex -> IO CString
-- | Gets joystick name. Returns @Nothing@ on error.
tryName :: JoystickIndex -> IO (Maybe String)
tryName :: Int -> IO (Maybe String)
tryName Int
idx = Int -> IO CString
sdlJoystickName Int
idx IO CString -> (CString -> IO (Maybe String)) -> IO (Maybe String)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (CString -> IO String) -> CString -> IO (Maybe String)
forall a b. (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
maybePeek CString -> IO String
peekCString

-- | Gets joystick name. Throws an exception on error.
name :: JoystickIndex -> IO String
name :: Int -> IO String
name = String -> IO (Maybe String) -> IO String
forall a. String -> IO (Maybe a) -> IO a
unwrapMaybe String
"SDL_JoystickName" (IO (Maybe String) -> IO String)
-> (Int -> IO (Maybe String)) -> Int -> IO String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO (Maybe String)
tryName

-- SDL_Joystick *SDL_JoystickOpen(int index);
foreign import ccall unsafe "SDL_JoystickOpen" sdlJoystickOpen :: JoystickIndex -> IO (Ptr JoystickStruct)
-- | Opens a joystick for use. Returns @Nothing@ on error.
tryOpen :: JoystickIndex -> IO (Maybe Joystick)
tryOpen :: Int -> IO (Maybe Joystick)
tryOpen Int
idx = Int -> IO (Ptr JoystickStruct)
sdlJoystickOpen Int
idx IO (Ptr JoystickStruct)
-> (Ptr JoystickStruct -> IO (Maybe Joystick))
-> IO (Maybe Joystick)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Ptr JoystickStruct -> IO Joystick)
-> Ptr JoystickStruct -> IO (Maybe Joystick)
forall a b. (Ptr a -> IO b) -> Ptr a -> IO (Maybe b)
maybePeek Ptr JoystickStruct -> IO Joystick
mkFinalizedJoystick

-- | Opens a joystick for use. Throws an exception on error.
open :: JoystickIndex -> IO Joystick
open :: Int -> IO Joystick
open = String -> IO (Maybe Joystick) -> IO Joystick
forall a. String -> IO (Maybe a) -> IO a
unwrapMaybe String
"SDL_JoystickOpen" (IO (Maybe Joystick) -> IO Joystick)
-> (Int -> IO (Maybe Joystick)) -> Int -> IO Joystick
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO (Maybe Joystick)
tryOpen

-- int SDL_JoystickOpened(int index);
foreign import ccall unsafe "SDL_JoystickOpened" sdlJoystickOpened :: JoystickIndex -> IO Int

-- | Determines if a joystick has been opened.
opened :: JoystickIndex -> IO Bool
opened :: Int -> IO Bool
opened = (Int -> Bool) -> IO Int -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> Bool
forall a. (Eq a, Num a) => a -> Bool
toBool (IO Int -> IO Bool) -> (Int -> IO Int) -> Int -> IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> IO Int
sdlJoystickOpened

-- int SDL_JoystickIndex(SDL_Joystick *joystick);
foreign import ccall unsafe "SDL_JoystickIndex" sdlJoystickIndex :: Ptr JoystickStruct -> JoystickIndex
-- | Gets the index of an @Joystick@.
index :: Joystick -> JoystickIndex
index :: Joystick -> Int
index Joystick
joystick
    = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
      Joystick -> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Joystick
joystick ((Ptr JoystickStruct -> IO Int) -> IO Int)
-> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$
      Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> IO Int)
-> (Ptr JoystickStruct -> Int) -> Ptr JoystickStruct -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr JoystickStruct -> Int
sdlJoystickIndex

-- int SDL_JoystickNumAxes(SDL_Joystick *joystick);
foreign import ccall unsafe "SDL_JoystickNumAxes" sdlJoystickNumAxes :: Ptr JoystickStruct -> Int
-- | Gets the number of joystick axes.
axesAvailable :: Joystick -> Int
axesAvailable :: Joystick -> Int
axesAvailable Joystick
joystick
    = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
      Joystick -> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Joystick
joystick ((Ptr JoystickStruct -> IO Int) -> IO Int)
-> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$
      Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> IO Int)
-> (Ptr JoystickStruct -> Int) -> Ptr JoystickStruct -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr JoystickStruct -> Int
sdlJoystickNumAxes

-- int SDL_JoystickNumBalls(SDL_Joystick *joystick);
foreign import ccall unsafe "SDL_JoystickNumBalls" sdlJoystickNumBalls :: Ptr JoystickStruct -> Int
-- | Gets the number of joystick trackballs.
ballsAvailable :: Joystick -> Int
ballsAvailable :: Joystick -> Int
ballsAvailable Joystick
joystick
    = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
      Joystick -> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Joystick
joystick ((Ptr JoystickStruct -> IO Int) -> IO Int)
-> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$
      Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> IO Int)
-> (Ptr JoystickStruct -> Int) -> Ptr JoystickStruct -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr JoystickStruct -> Int
sdlJoystickNumBalls

-- int SDL_JoystickNumHats(SDL_Joystick *joystick);
foreign import ccall unsafe "SDL_JoystickNumHats" sdlJoystickNumHats :: Ptr JoystickStruct -> Int
-- | Gets the number of joystick hats.
hatsAvailable :: Joystick -> Int
hatsAvailable :: Joystick -> Int
hatsAvailable Joystick
joystick
    = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
      Joystick -> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Joystick
joystick ((Ptr JoystickStruct -> IO Int) -> IO Int)
-> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$
      Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> IO Int)
-> (Ptr JoystickStruct -> Int) -> Ptr JoystickStruct -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr JoystickStruct -> Int
sdlJoystickNumHats

-- int SDL_JoystickNumButtons(SDL_Joystick *joystick);
foreign import ccall unsafe "SDL_JoystickNumButtons" sdlJoystickNumButtons :: Ptr JoystickStruct -> Int
-- | Gets the number of joystick buttons.
buttonsAvailable :: Joystick -> Int
buttonsAvailable :: Joystick -> Int
buttonsAvailable Joystick
joystick
    = IO Int -> Int
forall a. IO a -> a
unsafePerformIO (IO Int -> Int) -> IO Int -> Int
forall a b. (a -> b) -> a -> b
$
      Joystick -> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Joystick
joystick ((Ptr JoystickStruct -> IO Int) -> IO Int)
-> (Ptr JoystickStruct -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$
      Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> IO Int)
-> (Ptr JoystickStruct -> Int) -> Ptr JoystickStruct -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr JoystickStruct -> Int
sdlJoystickNumButtons

-- void SDL_JoystickUpdate(void);
-- | Updates the state of all joysticks.
foreign import ccall unsafe "SDL_JoystickUpdate" update :: IO ()

-- Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis);
foreign import ccall unsafe "SDL_JoystickGetAxis" joystickGetAxis :: Ptr JoystickStruct -> Int -> IO Int16
-- | Gets the current state of an axis.
getAxis :: Joystick -> Word8 -> IO Int16
getAxis :: Joystick -> Word8 -> IO Int16
getAxis Joystick
joystick Word8
axis
    = Joystick -> (Ptr JoystickStruct -> IO Int16) -> IO Int16
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Joystick
joystick ((Ptr JoystickStruct -> IO Int16) -> IO Int16)
-> (Ptr JoystickStruct -> IO Int16) -> IO Int16
forall a b. (a -> b) -> a -> b
$ \Ptr JoystickStruct
ptr ->
      Ptr JoystickStruct -> Int -> IO Int16
joystickGetAxis Ptr JoystickStruct
ptr (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
axis)

-- Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat);
foreign import ccall unsafe "SDL_JoystickGetHat" joystickGetHat :: Ptr JoystickStruct -> Int -> IO Word8
-- | Gets the current state of a joystick hat.
getHat :: Joystick -> Word8 -> IO [Hat]
getHat :: Joystick -> Word8 -> IO [Hat]
getHat Joystick
joystick Word8
axis
    = Joystick -> (Ptr JoystickStruct -> IO [Hat]) -> IO [Hat]
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Joystick
joystick ((Ptr JoystickStruct -> IO [Hat]) -> IO [Hat])
-> (Ptr JoystickStruct -> IO [Hat]) -> IO [Hat]
forall a b. (a -> b) -> a -> b
$ \Ptr JoystickStruct
ptr ->
      (Word8 -> [Hat]) -> IO Word8 -> IO [Hat]
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Word8 -> [Hat]
forall a b. (Bounded a, Enum a b, Bits b, Num b) => b -> [a]
fromBitmask(Word8 -> [Hat]) -> (Word8 -> Word8) -> Word8 -> [Hat]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Word8 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral) (Ptr JoystickStruct -> Int -> IO Word8
joystickGetHat Ptr JoystickStruct
ptr (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
axis))

-- Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button);
foreign import ccall unsafe "SDL_JoystickGetButton" joystickGetButton :: Ptr JoystickStruct -> Int -> IO Word8
-- | Gets the current state of a given button on a given joystick.
getButton :: Joystick -> Word8 -> IO Bool
getButton :: Joystick -> Word8 -> IO Bool
getButton Joystick
joystick Word8
button
    = Joystick -> (Ptr JoystickStruct -> IO Bool) -> IO Bool
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Joystick
joystick ((Ptr JoystickStruct -> IO Bool) -> IO Bool)
-> (Ptr JoystickStruct -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr JoystickStruct
ptr ->
      (Word8 -> Bool) -> IO Word8 -> IO Bool
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word8 -> Bool
forall a. (Eq a, Num a) => a -> Bool
toBool (Ptr JoystickStruct -> Int -> IO Word8
joystickGetButton Ptr JoystickStruct
ptr (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
button))

-- int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy);
foreign import ccall unsafe "SDL_JoystickGetBall" joystickGetBall
    :: Ptr JoystickStruct -> Int -> Ptr Int -> Ptr Int -> IO Int
-- | Gets relative trackball motion.
getBall :: Joystick -> Word8 -> IO (Maybe (Int16,Int16))
getBall :: Joystick -> Word8 -> IO (Maybe (Int16, Int16))
getBall Joystick
joystick Word8
ball
    = Joystick
-> (Ptr JoystickStruct -> IO (Maybe (Int16, Int16)))
-> IO (Maybe (Int16, Int16))
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr Joystick
joystick ((Ptr JoystickStruct -> IO (Maybe (Int16, Int16)))
 -> IO (Maybe (Int16, Int16)))
-> (Ptr JoystickStruct -> IO (Maybe (Int16, Int16)))
-> IO (Maybe (Int16, Int16))
forall a b. (a -> b) -> a -> b
$ \Ptr JoystickStruct
ptr ->
      (Ptr Int -> IO (Maybe (Int16, Int16))) -> IO (Maybe (Int16, Int16))
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Int -> IO (Maybe (Int16, Int16)))
 -> IO (Maybe (Int16, Int16)))
-> (Ptr Int -> IO (Maybe (Int16, Int16)))
-> IO (Maybe (Int16, Int16))
forall a b. (a -> b) -> a -> b
$ \Ptr Int
xrelPtr ->
      (Ptr Int -> IO (Maybe (Int16, Int16))) -> IO (Maybe (Int16, Int16))
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr Int -> IO (Maybe (Int16, Int16)))
 -> IO (Maybe (Int16, Int16)))
-> (Ptr Int -> IO (Maybe (Int16, Int16)))
-> IO (Maybe (Int16, Int16))
forall a b. (a -> b) -> a -> b
$ \Ptr Int
yrelPtr ->
      do Int
ret <- Ptr JoystickStruct -> Int -> Ptr Int -> Ptr Int -> IO Int
joystickGetBall Ptr JoystickStruct
ptr (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
ball) Ptr Int
xrelPtr Ptr Int
yrelPtr
         case Int
ret of
           Int
0 -> do [Int16
xrel,Int16
yrel] <- (Ptr Int -> IO Int16) -> [Ptr Int] -> IO [Int16]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ((Int -> Int16) -> IO Int -> IO Int16
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> Int16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IO Int -> IO Int16) -> (Ptr Int -> IO Int) -> Ptr Int -> IO Int16
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr Int -> IO Int
forall a. Storable a => Ptr a -> IO a
peek) [Ptr Int
xrelPtr,Ptr Int
yrelPtr]
                   Maybe (Int16, Int16) -> IO (Maybe (Int16, Int16))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Int16, Int16) -> IO (Maybe (Int16, Int16)))
-> Maybe (Int16, Int16) -> IO (Maybe (Int16, Int16))
forall a b. (a -> b) -> a -> b
$! (Int16, Int16) -> Maybe (Int16, Int16)
forall a. a -> Maybe a
Just (Int16
xrel,Int16
yrel)
           Int
_ -> Maybe (Int16, Int16) -> IO (Maybe (Int16, Int16))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Int16, Int16)
forall a. Maybe a
Nothing

-- | Force finalization of a previous opened @Joystick@. Only supported with GHC.
close :: Joystick -> IO ()
close :: Joystick -> IO ()
close =

{-# LINE 170 "Graphics/UI/SDL/Joystick.hsc" #-}
  finalizeForeignPtr

{-# LINE 174 "Graphics/UI/SDL/Joystick.hsc" #-}

-- void SDL_JoystickClose(SDL_Joystick *joystick);
foreign import ccall unsafe "&SDL_JoystickClose" sdlCloseJoystickFinal :: FunPtr (Ptr JoystickStruct -> IO ())

mkFinalizedJoystick :: Ptr JoystickStruct -> IO Joystick
mkFinalizedJoystick :: Ptr JoystickStruct -> IO Joystick
mkFinalizedJoystick = FinalizerPtr JoystickStruct -> Ptr JoystickStruct -> IO Joystick
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr JoystickStruct
sdlCloseJoystickFinal