{-# OPTIONS_GHC -optc-DOPTION_NO=sox_option_no #-}
{-# OPTIONS_GHC -optc-DOPTION_YES=sox_option_yes #-}
{-# OPTIONS_GHC -optc-DOPTION_DEFAULT=sox_option_default #-}
{-# LINE 1 "src/Sound/SoxLib/FFI.hsc" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Sound.SoxLib.FFI where




import qualified Foreign.C.String as CStr
import qualified Foreign.C.Types as C
import qualified Foreign.C.Error as E
import Foreign.Storable (Storable, sizeOf, alignment, peek, peekByteOff, poke, pokeByteOff, )
import Foreign.Ptr (FunPtr, Ptr, nullPtr, plusPtr, )

import Control.Applicative (pure, (<*>), )

import Data.Maybe.HT (toMaybe, )
import Data.Maybe (fromMaybe, )

-- we must import it unqualified, because Hsc calls it that way
import Data.Word
import Data.Int

import qualified Prelude as P
import Prelude hiding (Bool, init, length, )



newtype IOType = IOType Word32
{-# LINE 29 "src/Sound/SoxLib/FFI.hsc" #-}
   deriving (Storable)

ioFile  :: IOType
ioFile  = IOType 0
ioPipe  :: IOType
ioPipe  = IOType 1
ioURL  :: IOType
ioURL  = IOType 2

{-# LINE 36 "src/Sound/SoxLib/FFI.hsc" #-}

instance Show IOType where
   show (IOType 0) = "ioFile"
{-# LINE 39 "src/Sound/SoxLib/FFI.hsc" #-}
   show (IOType 1) = "ioPipe"
{-# LINE 40 "src/Sound/SoxLib/FFI.hsc" #-}
   show (IOType 2) = "ioURL"
{-# LINE 41 "src/Sound/SoxLib/FFI.hsc" #-}
   show (IOType n) = error $ "SoxLib.IOType.show: invalid number " ++ show n


type FormatPtr mode = Ptr (Format mode)

data Format mode =
   Format {
      filename :: FilePath,
      signalInfo :: SignalInfo,
      encodingInfo :: EncodingInfo,
      filetype :: FileType,
      -- oob :: OOB,
      seekable :: P.Bool,
      olength :: Int,
      clips :: Int,
      soxErrno :: E.Errno,
      soxErrStr :: String,
      fp :: Ptr C.CFile,
      ioType :: IOType,
      tellOff :: C.CLong,
      dataStart :: C.CLong,
      -- handler :: FormatHandler,
      priv :: Ptr ()
   }

instance Mode mode => Storable (Format mode) where
   sizeOf _    = (728)
{-# LINE 68 "src/Sound/SoxLib/FFI.hsc" #-}
   alignment _ = (8)
{-# LINE 69 "src/Sound/SoxLib/FFI.hsc" #-}
   peek p =
      pure Format
         <*> (peekEmptyCString =<< (\hsc_ptr -> peekByteOff hsc_ptr 0) p)
{-# LINE 72 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (\hsc_ptr -> peekByteOff hsc_ptr 8) p
{-# LINE 73 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (\hsc_ptr -> peekByteOff hsc_ptr 40) p
{-# LINE 74 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (fmap FileType . peekEmptyCString =<<
              (\hsc_ptr -> peekByteOff hsc_ptr 72) p)
{-# LINE 76 "src/Sound/SoxLib/FFI.hsc" #-}
         -- <*> #{peek sox_format_t, oob} p
         <*> peekBool ((\hsc_ptr -> hsc_ptr `plusPtr` 288) p)
{-# LINE 78 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> ((\hsc_ptr -> fmap fromIntegral (peekByteOff hsc_ptr 296 :: IO Word64)) p)
{-# LINE 79 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> ((\hsc_ptr -> fmap fromIntegral (peekByteOff hsc_ptr 304 :: IO Word64)) p)
{-# LINE 80 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> fmap E.Errno ((\hsc_ptr -> peekByteOff hsc_ptr 312) p)
{-# LINE 81 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (CStr.peekCStringLen ((\hsc_ptr -> hsc_ptr `plusPtr` 316) p, 256))
{-# LINE 82 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (\hsc_ptr -> peekByteOff hsc_ptr 576) p
{-# LINE 83 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (\hsc_ptr -> peekByteOff hsc_ptr 584) p
{-# LINE 84 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (\hsc_ptr -> peekByteOff hsc_ptr 592) p
{-# LINE 85 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (\hsc_ptr -> peekByteOff hsc_ptr 600) p
{-# LINE 86 "src/Sound/SoxLib/FFI.hsc" #-}
         -- <*> #{peek sox_format_t, handler} p
         <*> (\hsc_ptr -> peekByteOff hsc_ptr 720) p
{-# LINE 88 "src/Sound/SoxLib/FFI.hsc" #-}
   poke = error "SoxLib.Format.poke cannot be implemented because it requires temporary memory"


peekEmptyCString :: CStr.CString -> IO String
peekEmptyCString ptr =
   if ptr == nullPtr
     then return ""
     else CStr.peekCString ptr


class Mode mode where
   getModeChar :: Format mode -> C.CChar

data ReadMode  = ReadMode
data WriteMode = WriteMode

instance Mode ReadMode where
   getModeChar _ = CStr.castCharToCChar 'r'

instance Mode WriteMode where
   getModeChar _ = CStr.castCharToCChar 'w'


type Rate = Double

ignoreLength :: Int
ignoreLength = -1

data SignalInfo =
   SignalInfo {
      rate :: Maybe Rate,
      channels :: Maybe Int,
      precision :: Maybe Int,
      length :: Maybe Int,
      mult :: Maybe Double
   }
   deriving (Show)

defaultSignalInfo :: SignalInfo
defaultSignalInfo =
   SignalInfo Nothing Nothing Nothing Nothing Nothing

readSINumber :: (Num a, Eq a) => a -> Maybe a
readSINumber n =
   toMaybe (n /= 0) n
{-# LINE 133 "src/Sound/SoxLib/FFI.hsc" #-}

writeSINumber :: (Num a, Eq a) => Maybe a -> a
writeSINumber =
   fromMaybe (0)
{-# LINE 137 "src/Sound/SoxLib/FFI.hsc" #-}


instance Storable SignalInfo where
   sizeOf _    = (32)
{-# LINE 141 "src/Sound/SoxLib/FFI.hsc" #-}
   alignment _ = (8)
{-# LINE 142 "src/Sound/SoxLib/FFI.hsc" #-}
   peek p =
      pure SignalInfo
         <*> (fmap readSINumber $ peekDouble ((\hsc_ptr -> hsc_ptr `plusPtr` 0) p))
{-# LINE 145 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (fmap readSINumber $ (\hsc_ptr -> fmap fromIntegral (peekByteOff hsc_ptr 8 :: IO Word32)) p)
{-# LINE 146 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (fmap readSINumber $ (\hsc_ptr -> fmap fromIntegral (peekByteOff hsc_ptr 12 :: IO Word32)) p)
{-# LINE 147 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (fmap readSINumber $ (\hsc_ptr -> fmap fromIntegral (peekByteOff hsc_ptr 16 :: IO Word64)) p)
{-# LINE 148 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (do pd <- (\hsc_ptr -> peekByteOff hsc_ptr 24) p
{-# LINE 149 "src/Sound/SoxLib/FFI.hsc" #-}
                 if pd == nullPtr
                   then return Nothing
                   else fmap Just $ peekDouble pd)
   poke p v =
      pokeDouble ((\hsc_ptr -> hsc_ptr `plusPtr` 0) p) (writeSINumber $ rate v) >>
{-# LINE 154 "src/Sound/SoxLib/FFI.hsc" #-}
      (\hsc_ptr -> pokeByteOff hsc_ptr 8) p (writeSINumber $ channels  v) >>
{-# LINE 155 "src/Sound/SoxLib/FFI.hsc" #-}
      (\hsc_ptr -> pokeByteOff hsc_ptr 12) p (writeSINumber $ precision v) >>
{-# LINE 156 "src/Sound/SoxLib/FFI.hsc" #-}
      (\hsc_ptr -> pokeByteOff hsc_ptr 16) p (writeSINumber $ length    v) >>
{-# LINE 157 "src/Sound/SoxLib/FFI.hsc" #-}
      case mult v of
         Nothing -> (\hsc_ptr -> pokeByteOff hsc_ptr 24) p nullPtr
{-# LINE 159 "src/Sound/SoxLib/FFI.hsc" #-}
         Just _ ->
            error "SoxLib.SignalInfo.poke: Just-mult cannot simply be poked because it requires temporary memory"


newtype Option = Option Word32
{-# LINE 164 "src/Sound/SoxLib/FFI.hsc" #-}
   deriving (Storable)


{-# LINE 173 "src/Sound/SoxLib/FFI.hsc" #-}






{-# LINE 179 "src/Sound/SoxLib/FFI.hsc" #-}

optionNo  :: Option
optionNo  = Option 0
optionYes  :: Option
optionYes  = Option 1
optionDefault  :: Option
optionDefault  = Option 2

{-# LINE 185 "src/Sound/SoxLib/FFI.hsc" #-}

instance Show Option where
   show (Option 0) = "optionNo"
{-# LINE 188 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Option 1) = "optionYes"
{-# LINE 189 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Option 2) = "optionDefault"
{-# LINE 190 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Option n) = error $ "SoxLib.Option.show: invalid number " ++ show n


data EncodingInfo =
   EncodingInfo {
      encoding :: Encoding,
      bitsPerSample :: Int,
      compression :: Double,

      reverseBytes, reverseNibbles, reverseBits :: Option,
      oppositeEndian :: P.Bool
   }
   deriving (Show)

instance Storable EncodingInfo where
   sizeOf _    = (32)
{-# LINE 206 "src/Sound/SoxLib/FFI.hsc" #-}
   alignment _ = (8)
{-# LINE 207 "src/Sound/SoxLib/FFI.hsc" #-}
   peek p =
      pure EncodingInfo
         <*> ((\hsc_ptr -> peekByteOff hsc_ptr 0) p)
{-# LINE 210 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> ((\hsc_ptr -> fmap fromIntegral (peekByteOff hsc_ptr 4 :: IO Word32)) p)
{-# LINE 211 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (peekDouble $ (\hsc_ptr -> hsc_ptr `plusPtr` 8) p)
{-# LINE 212 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> ((\hsc_ptr -> peekByteOff hsc_ptr 16) p)
{-# LINE 213 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> ((\hsc_ptr -> peekByteOff hsc_ptr 20) p)
{-# LINE 214 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> ((\hsc_ptr -> peekByteOff hsc_ptr 24) p)
{-# LINE 215 "src/Sound/SoxLib/FFI.hsc" #-}
         <*> (peekBool $ (\hsc_ptr -> hsc_ptr `plusPtr` 28) p)
{-# LINE 216 "src/Sound/SoxLib/FFI.hsc" #-}
   poke p v =
      (\hsc_ptr -> pokeByteOff hsc_ptr 0) p (encoding      v) >>
{-# LINE 218 "src/Sound/SoxLib/FFI.hsc" #-}
      (\hsc_ptr hsc_x -> pokeByteOff hsc_ptr 4 (fromIntegral hsc_x :: Word32)) p (bitsPerSample v) >>
{-# LINE 219 "src/Sound/SoxLib/FFI.hsc" #-}
      pokeDouble ((\hsc_ptr -> hsc_ptr `plusPtr` 8) p) (compression v) >>
{-# LINE 220 "src/Sound/SoxLib/FFI.hsc" #-}
      (\hsc_ptr -> pokeByteOff hsc_ptr 16) p (reverseBytes   v) >>
{-# LINE 221 "src/Sound/SoxLib/FFI.hsc" #-}
      (\hsc_ptr -> pokeByteOff hsc_ptr 20) p (reverseNibbles v) >>
{-# LINE 222 "src/Sound/SoxLib/FFI.hsc" #-}
      (\hsc_ptr -> pokeByteOff hsc_ptr 24) p (reverseBits    v) >>
{-# LINE 223 "src/Sound/SoxLib/FFI.hsc" #-}
      pokeBool ((\hsc_ptr -> hsc_ptr `plusPtr` 28) p) (oppositeEndian v)
{-# LINE 224 "src/Sound/SoxLib/FFI.hsc" #-}


newtype Bool = Bool Int32
{-# LINE 227 "src/Sound/SoxLib/FFI.hsc" #-}
   deriving (Show, Eq, Storable)

false  :: Bool
false  = Bool 0
true  :: Bool
true  = Bool 1

{-# LINE 233 "src/Sound/SoxLib/FFI.hsc" #-}

packBool :: P.Bool -> Bool
packBool False = false
packBool True = true

unpackBool :: Bool -> P.Bool
unpackBool x = x/=false


peekBool :: Ptr Bool -> IO P.Bool
peekBool p = fmap unpackBool $ peek p

pokeBool :: Ptr Bool -> P.Bool -> IO ()
pokeBool p b = poke p $ packBool b


peekDouble :: Ptr C.CDouble -> IO Double
peekDouble p = fmap realToFrac $ peek p

pokeDouble :: Ptr C.CDouble -> Double -> IO ()
pokeDouble p x = poke p $ realToFrac x


newtype Encoding = Encoding Word32
{-# LINE 257 "src/Sound/SoxLib/FFI.hsc" #-}
   deriving (Storable)

instance Bounded Encoding where
   minBound = Encoding 0
{-# LINE 261 "src/Sound/SoxLib/FFI.hsc" #-}
   maxBound = Encoding $ pred 29
{-# LINE 262 "src/Sound/SoxLib/FFI.hsc" #-}

encodingUnknown     :: Encoding
encodingUnknown     = Encoding 0
encodingSign2       :: Encoding
encodingSign2       = Encoding 1
encodingUnsigned    :: Encoding
encodingUnsigned    = Encoding 2
encodingFloat       :: Encoding
encodingFloat       = Encoding 3
encodingFloatText   :: Encoding
encodingFloatText   = Encoding 4
encodingFlac        :: Encoding
encodingFlac        = Encoding 5
encodingHcom        :: Encoding
encodingHcom        = Encoding 6
encodingWavpack     :: Encoding
encodingWavpack     = Encoding 7
encodingWavpackf    :: Encoding
encodingWavpackf    = Encoding 8
encodingUlaw        :: Encoding
encodingUlaw        = Encoding 9
encodingAlaw        :: Encoding
encodingAlaw        = Encoding 10
encodingG721        :: Encoding
encodingG721        = Encoding 11
encodingG723        :: Encoding
encodingG723        = Encoding 12
encodingClADPCM     :: Encoding
encodingClADPCM     = Encoding 13
encodingClADPCM16   :: Encoding
encodingClADPCM16   = Encoding 14
encodingMsADPCM     :: Encoding
encodingMsADPCM     = Encoding 15
encodingImaADPCM    :: Encoding
encodingImaADPCM    = Encoding 16
encodingOkiADPCM    :: Encoding
encodingOkiADPCM    = Encoding 17
encodingDPCM        :: Encoding
encodingDPCM        = Encoding 18
encodingDWVW        :: Encoding
encodingDWVW        = Encoding 19
encodingDWVWN       :: Encoding
encodingDWVWN       = Encoding 20
encodingGSM         :: Encoding
encodingGSM         = Encoding 21
encodingMP3         :: Encoding
encodingMP3         = Encoding 22
encodingVorbis      :: Encoding
encodingVorbis      = Encoding 23
encodingAmrWB       :: Encoding
encodingAmrWB       = Encoding 24
encodingAmrNB       :: Encoding
encodingAmrNB       = Encoding 25
encodingCVSD        :: Encoding
encodingCVSD        = Encoding 26
encodingLPC10       :: Encoding
encodingLPC10       = Encoding 27

{-# LINE 293 "src/Sound/SoxLib/FFI.hsc" #-}

instance Show Encoding where
   show (Encoding 0) = "encodingUnknown"
{-# LINE 296 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 1) = "encodingSign2"
{-# LINE 297 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 2) = "encodingUnsigned"
{-# LINE 298 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 3) = "encodingFloat"
{-# LINE 299 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 4) = "encodingFloatText"
{-# LINE 300 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 5) = "encodingFlac"
{-# LINE 301 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 6) = "encodingHcom"
{-# LINE 302 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 7) = "encodingWavpack"
{-# LINE 303 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 8) = "encodingWavpackf"
{-# LINE 304 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 9) = "encodingUlaw"
{-# LINE 305 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 10) = "encodingAlaw"
{-# LINE 306 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 11) = "encodingG721"
{-# LINE 307 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 12) = "encodingG723"
{-# LINE 308 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 13) = "encodingClADPCM"
{-# LINE 309 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 14) = "encodingClADPCM16"
{-# LINE 310 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 15) = "encodingMsADPCM"
{-# LINE 311 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 16) = "encodingImaADPCM"
{-# LINE 312 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 17) = "encodingOkiADPCM"
{-# LINE 313 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 18) = "encodingDPCM"
{-# LINE 314 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 19) = "encodingDWVW"
{-# LINE 315 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 20) = "encodingDWVWN"
{-# LINE 316 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 21) = "encodingGSM"
{-# LINE 317 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 22) = "encodingMP3"
{-# LINE 318 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 23) = "encodingVorbis"
{-# LINE 319 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 24) = "encodingAmrWB"
{-# LINE 320 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 25) = "encodingAmrNB"
{-# LINE 321 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 26) = "encodingCVSD"
{-# LINE 322 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding 27) = "encodingLPC10"
{-# LINE 323 "src/Sound/SoxLib/FFI.hsc" #-}
   show (Encoding n) = "(Encoding " ++ show n ++ ")"



newtype FileType = FileType {unFileType :: String}

instance Show FileType where
   showsPrec prec (FileType str) =
      showParen (prec>=10) $ showString "FileType " . showString str

type CFileType = CStr.CString
type Sample = Int32
{-# LINE 335 "src/Sound/SoxLib/FFI.hsc" #-}
type OOB = ()
-- type FormatHandler = ()
type Whence = C.CInt


foreign import ccall unsafe "sox.h sox_init"
   init :: IO C.CInt

foreign import ccall unsafe "sox.h sox_quit"
   quit :: IO C.CInt

foreign import ccall unsafe "sox.h sox_format_init"
   formatInit :: IO C.CInt

foreign import ccall unsafe "sox.h sox_format_quit"
   formatQuit :: IO ()

foreign import ccall unsafe "sox.h sox_open_read"
   openRead :: CStr.CString -> Ptr SignalInfo -> Ptr EncodingInfo -> CFileType -> IO (FormatPtr ReadMode)

foreign import ccall safe "sox.h sox_open_mem_read"
   openMemRead :: Ptr Word8 -> C.CSize -> Ptr SignalInfo -> Ptr EncodingInfo -> CStr.CString -> IO (FormatPtr ReadMode)

foreign import ccall safe "sox.h sox_open_write"
   openWrite :: CStr.CString -> Ptr SignalInfo -> Ptr EncodingInfo -> CFileType -> Ptr OOB -> FunPtr (CStr.CString -> IO Bool) -> IO (FormatPtr WriteMode)

foreign import ccall safe "sox.h sox_open_mem_write"
   openMemWrite :: Ptr Word8 -> C.CSize -> Ptr SignalInfo -> Ptr EncodingInfo -> CFileType -> Ptr OOB -> IO (FormatPtr WriteMode)

foreign import ccall safe "sox.h sox_open_memstream_write"
   openMemstreamWrite :: Ptr (Ptr Word8) -> Ptr C.CSize -> Ptr SignalInfo -> Ptr EncodingInfo -> CFileType -> Ptr OOB -> IO (FormatPtr WriteMode)

foreign import ccall unsafe "sox.h sox_read"
   read :: FormatPtr ReadMode -> Ptr Sample -> C.CSize -> IO C.CSize

foreign import ccall unsafe "sox.h sox_write"
   write :: FormatPtr WriteMode -> Ptr Sample -> C.CSize -> IO C.CSize

foreign import ccall unsafe "sox.h sox_close"
   close :: FormatPtr mode -> IO C.CInt

foreign import ccall unsafe "sox.h sox_seek"
   seek :: FormatPtr mode -> C.CSize -> Whence -> IO C.CInt


-- Is it safe on every platform to pretend that (IO CInt) is (IO ()) ?
foreign import ccall unsafe "sox.h &sox_close"
   closeFun :: FunPtr (FormatPtr mode -> IO ())