    module SDL.Raw.Audio (
      -- * Audio Device Management, Playing and Recording
      audioInit,
      audioQuit,
      buildAudioCVT,
      clearQueuedAudio,
      closeAudio,
      closeAudioDevice,
      convertAudio,
      freeWAV,
      getAudioDeviceName,
      getAudioDeviceStatus,
      getAudioDriver,
      getAudioStatus,
      getCurrentAudioDriver,
      getNumAudioDevices,
      getNumAudioDrivers,
      getQueuedAudioSize,
      loadWAV,
      loadWAV_RW,
      lockAudio,
      lockAudioDevice,
      mixAudio,
      mixAudioFormat,
      openAudio,
      openAudioDevice,
      pauseAudio,
      pauseAudioDevice,
      queueAudio,
      unlockAudio,
      unlockAudioDevice
    ) where

    import Control.Monad.IO.Class
    import Data.Word
    import Foreign.C.String
    import Foreign.C.Types
    import Foreign.Ptr
    import SDL.Raw.Enum
    import SDL.Raw.Filesystem
    import SDL.Raw.Types

    foreign import ccall "SDL.h SDL_AudioInit" audioInitFFI :: CString -> IO CInt
    foreign import ccall "SDL.h SDL_AudioQuit" audioQuitFFI :: IO ()
    foreign import ccall "SDL.h SDL_BuildAudioCVT" buildAudioCVTFFI :: Ptr AudioCVT -> AudioFormat -> Word8 -> CInt -> AudioFormat -> Word8 -> CInt -> IO CInt
    foreign import ccall "SDL.h SDL_ClearQueuedAudio" clearQueuedAudioFFI :: AudioDeviceID -> IO ()
    foreign import ccall "SDL.h SDL_CloseAudio" closeAudioFFI :: IO ()
    foreign import ccall "SDL.h SDL_CloseAudioDevice" closeAudioDeviceFFI :: AudioDeviceID -> IO ()
    foreign import ccall "SDL.h SDL_ConvertAudio" convertAudioFFI :: Ptr AudioCVT -> IO CInt
    foreign import ccall "SDL.h SDL_FreeWAV" freeWAVFFI :: Ptr Word8 -> IO ()
    foreign import ccall "SDL.h SDL_GetAudioDeviceName" getAudioDeviceNameFFI :: CInt -> CInt -> IO CString
    foreign import ccall "SDL.h SDL_GetAudioDeviceStatus" getAudioDeviceStatusFFI :: AudioDeviceID -> IO AudioStatus
    foreign import ccall "SDL.h SDL_GetAudioDriver" getAudioDriverFFI :: CInt -> IO CString
    foreign import ccall "SDL.h SDL_GetAudioStatus" getAudioStatusFFI :: IO AudioStatus
    foreign import ccall "SDL.h SDL_GetCurrentAudioDriver" getCurrentAudioDriverFFI :: IO CString
    foreign import ccall "SDL.h SDL_GetNumAudioDevices" getNumAudioDevicesFFI :: CInt -> IO CInt
    foreign import ccall "SDL.h SDL_GetNumAudioDrivers" getNumAudioDriversFFI :: IO CInt
    foreign import ccall "SDL.h SDL_GetQueuedAudioSize" getQueuedAudioSizeFFI :: AudioDeviceID -> IO Word32
    foreign import ccall "SDL.h SDL_LoadWAV_RW" loadWAV_RWFFI :: Ptr RWops -> CInt -> Ptr AudioSpec -> Ptr (Ptr Word8) -> Ptr Word32 -> IO (Ptr AudioSpec)
    foreign import ccall "SDL.h SDL_LockAudio" lockAudioFFI :: IO ()
    foreign import ccall "SDL.h SDL_LockAudioDevice" lockAudioDeviceFFI :: AudioDeviceID -> IO ()
    foreign import ccall "SDL.h SDL_MixAudio" mixAudioFFI :: Ptr Word8 -> Ptr Word8 -> Word32 -> CInt -> IO ()
    foreign import ccall "SDL.h SDL_MixAudioFormat" mixAudioFormatFFI :: Ptr Word8 -> Ptr Word8 -> AudioFormat -> Word32 -> CInt -> IO ()
    foreign import ccall "SDL.h SDL_OpenAudio" openAudioFFI :: Ptr AudioSpec -> Ptr AudioSpec -> IO CInt
    foreign import ccall "SDL.h SDL_OpenAudioDevice" openAudioDeviceFFI :: CString -> CInt -> Ptr AudioSpec -> Ptr AudioSpec -> CInt -> IO AudioDeviceID
    foreign import ccall "SDL.h SDL_PauseAudio" pauseAudioFFI :: CInt -> IO ()
    foreign import ccall "SDL.h SDL_PauseAudioDevice" pauseAudioDeviceFFI :: AudioDeviceID -> CInt -> IO ()
    foreign import ccall "SDL.h SDL_QueueAudio" queueAudioFFI :: AudioDeviceID -> Ptr () -> Word32 -> IO CInt
    foreign import ccall "SDL.h SDL_UnlockAudio" unlockAudioFFI :: IO ()
    foreign import ccall "SDL.h SDL_UnlockAudioDevice" unlockAudioDeviceFFI :: AudioDeviceID -> IO ()

    audioInit :: MonadIO m => CString -> m CInt
    audioInit v1 = liftIO $ audioInitFFI v1
    {-# INLINE audioInit #-}

    audioQuit :: MonadIO m => m ()
    audioQuit = liftIO audioQuitFFI
    {-# INLINE audioQuit #-}

    buildAudioCVT :: MonadIO m => Ptr AudioCVT -> AudioFormat -> Word8 -> CInt -> AudioFormat -> Word8 -> CInt -> m CInt
    buildAudioCVT v1 v2 v3 v4 v5 v6 v7 = liftIO $ buildAudioCVTFFI v1 v2 v3 v4 v5 v6 v7
    {-# INLINE buildAudioCVT #-}

    clearQueuedAudio :: MonadIO m => AudioDeviceID -> m ()
    clearQueuedAudio v1 = liftIO $ clearQueuedAudioFFI v1
    {-# INLINE clearQueuedAudio #-}

    closeAudio :: MonadIO m => m ()
    closeAudio = liftIO closeAudioFFI
    {-# INLINE closeAudio #-}

    closeAudioDevice :: MonadIO m => AudioDeviceID -> m ()
    closeAudioDevice v1 = liftIO $ closeAudioDeviceFFI v1
    {-# INLINE closeAudioDevice #-}

    convertAudio :: MonadIO m => Ptr AudioCVT -> m CInt
    convertAudio v1 = liftIO $ convertAudioFFI v1
    {-# INLINE convertAudio #-}

    freeWAV :: MonadIO m => Ptr Word8 -> m ()
    freeWAV v1 = liftIO $ freeWAVFFI v1
    {-# INLINE freeWAV #-}

    getAudioDeviceName :: MonadIO m => CInt -> CInt -> m CString
    getAudioDeviceName v1 v2 = liftIO $ getAudioDeviceNameFFI v1 v2
    {-# INLINE getAudioDeviceName #-}

    getAudioDeviceStatus :: MonadIO m => AudioDeviceID -> m AudioStatus
    getAudioDeviceStatus v1 = liftIO $ getAudioDeviceStatusFFI v1
    {-# INLINE getAudioDeviceStatus #-}

    getAudioDriver :: MonadIO m => CInt -> m CString
    getAudioDriver v1 = liftIO $ getAudioDriverFFI v1
    {-# INLINE getAudioDriver #-}

    getAudioStatus :: MonadIO m => m AudioStatus
    getAudioStatus = liftIO getAudioStatusFFI
    {-# INLINE getAudioStatus #-}

    getCurrentAudioDriver :: MonadIO m => m CString
    getCurrentAudioDriver = liftIO getCurrentAudioDriverFFI
    {-# INLINE getCurrentAudioDriver #-}

    getNumAudioDevices :: MonadIO m => CInt -> m CInt
    getNumAudioDevices v1 = liftIO $ getNumAudioDevicesFFI v1
    {-# INLINE getNumAudioDevices #-}

    getNumAudioDrivers :: MonadIO m => m CInt
    getNumAudioDrivers = liftIO getNumAudioDriversFFI
    {-# INLINE getNumAudioDrivers #-}

    getQueuedAudioSize :: MonadIO m => AudioDeviceID -> m Word32
    getQueuedAudioSize v1 = liftIO $ getQueuedAudioSizeFFI v1
    {-# INLINE getQueuedAudioSize #-}

    loadWAV :: MonadIO m => CString -> Ptr AudioSpec -> Ptr (Ptr Word8) -> Ptr Word32 -> m (Ptr AudioSpec)
    loadWAV file spec audio_buf audio_len = liftIO $ do
      rw <- withCString "rb" $ rwFromFile file
      loadWAV_RW rw 1 spec audio_buf audio_len
    {-# INLINE loadWAV #-}

    loadWAV_RW :: MonadIO m => Ptr RWops -> CInt -> Ptr AudioSpec -> Ptr (Ptr Word8) -> Ptr Word32 -> m (Ptr AudioSpec)
    loadWAV_RW v1 v2 v3 v4 v5 = liftIO $ loadWAV_RWFFI v1 v2 v3 v4 v5
    {-# INLINE loadWAV_RW #-}

    lockAudio :: MonadIO m => m ()
    lockAudio = liftIO lockAudioFFI
    {-# INLINE lockAudio #-}

    lockAudioDevice :: MonadIO m => AudioDeviceID -> m ()
    lockAudioDevice v1 = liftIO $ lockAudioDeviceFFI v1
    {-# INLINE lockAudioDevice #-}

    mixAudio :: MonadIO m => Ptr Word8 -> Ptr Word8 -> Word32 -> CInt -> m ()
    mixAudio v1 v2 v3 v4 = liftIO $ mixAudioFFI v1 v2 v3 v4
    {-# INLINE mixAudio #-}

    mixAudioFormat :: MonadIO m => Ptr Word8 -> Ptr Word8 -> AudioFormat -> Word32 -> CInt -> m ()
    mixAudioFormat v1 v2 v3 v4 v5 = liftIO $ mixAudioFormatFFI v1 v2 v3 v4 v5
    {-# INLINE mixAudioFormat #-}

    openAudio :: MonadIO m => Ptr AudioSpec -> Ptr AudioSpec -> m CInt
    openAudio v1 v2 = liftIO $ openAudioFFI v1 v2
    {-# INLINE openAudio #-}

    openAudioDevice :: MonadIO m => CString -> CInt -> Ptr AudioSpec -> Ptr AudioSpec -> CInt -> m AudioDeviceID
    openAudioDevice v1 v2 v3 v4 v5 = liftIO $ openAudioDeviceFFI v1 v2 v3 v4 v5
    {-# INLINE openAudioDevice #-}

    pauseAudio :: MonadIO m => CInt -> m ()
    pauseAudio v1 = liftIO $ pauseAudioFFI v1
    {-# INLINE pauseAudio #-}

    pauseAudioDevice :: MonadIO m => AudioDeviceID -> CInt -> m ()
    pauseAudioDevice v1 v2 = liftIO $ pauseAudioDeviceFFI v1 v2
    {-# INLINE pauseAudioDevice #-}

    queueAudio :: MonadIO m => AudioDeviceID -> Ptr () -> Word32 -> m CInt
    queueAudio v1 v2 v3 = liftIO $ queueAudioFFI v1 v2 v3
    {-# INLINE queueAudio #-}

    unlockAudio :: MonadIO m => m ()
    unlockAudio = liftIO unlockAudioFFI
    {-# INLINE unlockAudio #-}

    unlockAudioDevice :: MonadIO m => AudioDeviceID -> m ()
    unlockAudioDevice v1 = liftIO $ unlockAudioDeviceFFI v1
    {-# INLINE unlockAudioDevice #-}