{-# LINE 1 "Sound/MikMod/Module.hsc" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LINE 2 "Sound/MikMod/Module.hsc" #-}
module Sound.MikMod.Module where

import Foreign.Ptr
import Foreign.Storable
import Foreign.C.Types
import Foreign.C.String
import Data.Functor
import Control.Applicative

import Sound.MikMod.Synonyms
import Sound.MikMod.Types
import Sound.MikMod.Flags


{-# LINE 16 "Sound/MikMod/Module.hsc" #-}

-- | Get a report of the static aspects of a module.
getModuleInfo :: ModuleHandle -> IO ModuleInfo
getModuleInfo ptr = ModuleInfo <$>
  (peekCStringError =<< (((\hsc_ptr -> peekByteOff hsc_ptr 0)) ptr :: IO CString)) <*>
{-# LINE 21 "Sound/MikMod/Module.hsc" #-}
  (peekCStringError =<< (((\hsc_ptr -> peekByteOff hsc_ptr 8)) ptr :: IO CString)) <*>
{-# LINE 22 "Sound/MikMod/Module.hsc" #-}
  (peekCStringMaybe =<< (((\hsc_ptr -> peekByteOff hsc_ptr 16)) ptr :: IO CString)) <*>
{-# LINE 23 "Sound/MikMod/Module.hsc" #-}
  (unpackFlags <$> (((\hsc_ptr -> peekByteOff hsc_ptr 24)) ptr :: IO UWORD)) <*>
{-# LINE 24 "Sound/MikMod/Module.hsc" #-}
  (fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 26)) ptr :: IO UBYTE)) <*>
{-# LINE 25 "Sound/MikMod/Module.hsc" #-}
  (fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 27)) ptr :: IO UBYTE)) <*>
{-# LINE 26 "Sound/MikMod/Module.hsc" #-}
  (fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 28)) ptr :: IO UWORD)) <*>
{-# LINE 27 "Sound/MikMod/Module.hsc" #-}
  (fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 30)) ptr :: IO UWORD)) <*>
{-# LINE 28 "Sound/MikMod/Module.hsc" #-}
  (fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 32)) ptr :: IO UWORD)) <*>
{-# LINE 29 "Sound/MikMod/Module.hsc" #-}
  (fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 34)) ptr :: IO UWORD)) <*>
{-# LINE 30 "Sound/MikMod/Module.hsc" #-}
  unpackInstrumentNames ptr

peekCStringMaybe :: CString -> IO (Maybe String)
peekCStringMaybe cstr | cstr == nullPtr = return Nothing
                      | otherwise = Just <$> peekCString cstr

peekCStringError :: CString -> IO String
peekCStringError cstr | cstr == nullPtr = error "peekCStringError NULL"
                      | otherwise = peekCString cstr

unpackInstrumentNames :: Ptr Module -> IO (Maybe [String])
unpackInstrumentNames mod = do
  n <- fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 32)) mod :: IO UWORD)
{-# LINE 43 "Sound/MikMod/Module.hsc" #-}
  ins0 <- ((\hsc_ptr -> peekByteOff hsc_ptr 40)) mod :: IO (Ptr Instrument)
{-# LINE 44 "Sound/MikMod/Module.hsc" #-}
  if (ins0 == nullPtr)
    then return Nothing
    else do
      let ptrs = map (\i -> ins0 `plusPtr` (sizeOfInstrument * i)) [0..n-1]
      Just <$> mapM getInstrumentName ptrs
  
getInstrumentName :: Ptr Instrument -> IO String
getInstrumentName ptr = peekCString =<< (((\hsc_ptr -> peekByteOff hsc_ptr 0)) ptr :: IO CString)
{-# LINE 52 "Sound/MikMod/Module.hsc" #-}

-- | Get handles to the samples contained in a module. I don't think it would
-- be wise to call sampleFree on these samples.
getModuleSamples :: ModuleHandle -> IO [SampleHandle]
getModuleSamples mod = do
  nsamps <- moduleNumSamples <$> getModuleInfo mod
  samps <- ((\hsc_ptr -> peekByteOff hsc_ptr 48)) mod
{-# LINE 59 "Sound/MikMod/Module.hsc" #-}
  let stride = ((88))
{-# LINE 60 "Sound/MikMod/Module.hsc" #-}
  return (map (\i -> samps `plusPtr` (i*stride)) [0..nsamps-1])

sizeOfInstrument :: Int
sizeOfInstrument = ((784))
{-# LINE 64 "Sound/MikMod/Module.hsc" #-}

-- | During playback, the number of active channels (not counting NNA channels). 
getModuleRealChannels :: ModuleHandle -> IO Int
getModuleRealChannels mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 56)) mod :: IO UBYTE)
{-# LINE 68 "Sound/MikMod/Module.hsc" #-}

-- | During playback, the total number of channels (including NNA channels). 
getModuleTotalChannels :: ModuleHandle -> IO Int
getModuleTotalChannels mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 57)) mod :: IO UBYTE)
{-# LINE 72 "Sound/MikMod/Module.hsc" #-}

-- | Elapsed song time in units of 1/1024 seconds. That's not milliseconds.
getModuleSongTime :: ModuleHandle -> IO Integer
getModuleSongTime mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 288)) mod :: IO ULONG)
{-# LINE 76 "Sound/MikMod/Module.hsc" #-}

-- | Current song position.
getModuleSongPosition :: ModuleHandle -> IO Int
getModuleSongPosition mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 286)) mod :: IO SWORD)
{-# LINE 80 "Sound/MikMod/Module.hsc" #-}

-- | Current position in the pattern being played.
getModulePatternPosition :: ModuleHandle -> IO Int
getModulePatternPosition mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 284)) mod :: IO UWORD)
{-# LINE 84 "Sound/MikMod/Module.hsc" #-}

-- | Set the initial speed of the module. Must be in range 1 - 32.
setModuleInitSpeed :: ModuleHandle -> Int -> IO ()
setModuleInitSpeed mod s = ((\hsc_ptr -> pokeByteOff hsc_ptr 60)) mod (fromIntegral s :: UBYTE)
{-# LINE 88 "Sound/MikMod/Module.hsc" #-}

getModuleInitSpeed :: ModuleHandle -> IO Int
getModuleInitSpeed mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 60)) mod :: IO UBYTE)
{-# LINE 91 "Sound/MikMod/Module.hsc" #-}

-- | Set the initial tempo of the module. Must be in range 32 - 255.
setModuleInitTempo :: ModuleHandle -> Int -> IO ()
setModuleInitTempo mod temp = ((\hsc_ptr -> pokeByteOff hsc_ptr 62)) mod (fromIntegral temp :: UBYTE)
{-# LINE 95 "Sound/MikMod/Module.hsc" #-}

getModuleInitTempo :: ModuleHandle -> IO Int
getModuleInitTempo mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 62)) mod :: IO UBYTE)
{-# LINE 98 "Sound/MikMod/Module.hsc" #-}

-- | Set the pan position of a channel in a module.
setModulePanning :: ModuleHandle
                 -> Int -- ^ Channel to set panning on.
                 -> Int -- ^ Pan position from 0 (far left) to 255 (far right).
                 -> IO ()
setModulePanning mod ch pan = do
  nchans <- moduleNumChannels <$> getModuleInfo mod
  chans <- ((\hsc_ptr -> peekByteOff hsc_ptr 66)) mod :: IO (Ptr UWORD)
{-# LINE 107 "Sound/MikMod/Module.hsc" #-}
  if (ch >= 0 && ch < nchans)
    then pokeElemOff chans ch (fromIntegral pan)
    else return ()

-- | Query the pan position of a particular channel.
getModulePanning :: ModuleHandle -> Int -> IO Int
getModulePanning mod ch = do
  nchans <- moduleNumChannels <$> getModuleInfo mod
  chans <- ((\hsc_ptr -> peekByteOff hsc_ptr 66)) mod :: IO (Ptr UWORD)
{-# LINE 116 "Sound/MikMod/Module.hsc" #-}
  if (ch >= 0 && ch < nchans)
    then fromIntegral <$> peekElemOff chans ch
    else return 0

-- | Set the volume of a channel in a module.
setModuleChannelVolume :: ModuleHandle
                       -> Int -- ^ Channel to set volume on.
                       -> Int -- ^ Volume level from 0 to 128.
                       -> IO ()
setModuleChannelVolume mod ch vol = do
  nchans <- moduleNumChannels <$> getModuleInfo mod
  chans <- ((\hsc_ptr -> peekByteOff hsc_ptr 194)) mod :: IO (Ptr UBYTE)
{-# LINE 128 "Sound/MikMod/Module.hsc" #-}
  if (ch >= 0 && ch < nchans)
    then pokeElemOff chans ch (fromIntegral vol)
    else return ()

-- | Query the volume of a particular channel.
getModuleChannelVolume :: ModuleHandle -> Int -> IO Int
getModuleChannelVolume mod ch = do
  nchans <- moduleNumChannels <$> getModuleInfo mod
  chans <- ((\hsc_ptr -> peekByteOff hsc_ptr 194)) mod :: IO (Ptr UBYTE)
{-# LINE 137 "Sound/MikMod/Module.hsc" #-}
  if (ch >= 0 && ch < nchans)
    then fromIntegral <$> peekElemOff chans ch
    else return 0

-- | Set the tempo of the module. See 'Sound.MikMod.playerSetTempo'.
setModuleBPM :: ModuleHandle -> Int -> IO ()
setModuleBPM mod bpm = ((\hsc_ptr -> pokeByteOff hsc_ptr 258)) mod (fromIntegral bpm :: UWORD)
{-# LINE 144 "Sound/MikMod/Module.hsc" #-}

getModuleBPM :: ModuleHandle -> IO Int
getModuleBPM mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 258)) mod :: IO UWORD)
{-# LINE 147 "Sound/MikMod/Module.hsc" #-}

-- | Set the speed of the module. See 'Sound.MikMod.playerSetSpeed'.
setModuleSongSpeed :: ModuleHandle -> Int -> IO ()
setModuleSongSpeed mod spd = ((\hsc_ptr -> pokeByteOff hsc_ptr 260)) mod (fromIntegral spd :: UBYTE)
{-# LINE 151 "Sound/MikMod/Module.hsc" #-}

getModuleSongSpeed :: ModuleHandle -> IO Int
getModuleSongSpeed mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 260)) mod :: IO UBYTE)
{-# LINE 154 "Sound/MikMod/Module.hsc" #-}

-- | Set the Protracker extended speed effect flag. True means process the
-- effect. Default is True.
setModuleExtSpeed :: ModuleHandle -> Bool -> IO ()
setModuleExtSpeed mod flag = ((\hsc_ptr -> pokeByteOff hsc_ptr 264)) mod (encodeBool flag)
{-# LINE 159 "Sound/MikMod/Module.hsc" #-}

getModuleExtSpeed :: ModuleHandle -> IO Bool
getModuleExtSpeed mod = decodeBool <$> ((\hsc_ptr -> peekByteOff hsc_ptr 264)) mod
{-# LINE 162 "Sound/MikMod/Module.hsc" #-}

-- | Set the pan flag. True means process pan effects. Default is True.
setModulePanFlag :: ModuleHandle -> Bool -> IO ()
setModulePanFlag mod flag = ((\hsc_ptr -> pokeByteOff hsc_ptr 268)) mod (encodeBool flag)
{-# LINE 166 "Sound/MikMod/Module.hsc" #-}

getModulePanFlag :: ModuleHandle -> IO Bool
getModulePanFlag mod = decodeBool <$> ((\hsc_ptr -> peekByteOff hsc_ptr 268)) mod
{-# LINE 169 "Sound/MikMod/Module.hsc" #-}

-- | Set the wrap flag. True means repeat from restart position at end of
-- song. Default is False, song ends.
setModuleWrap :: ModuleHandle -> Bool -> IO ()
setModuleWrap mod flag = ((\hsc_ptr -> pokeByteOff hsc_ptr 272)) mod (encodeBool flag)
{-# LINE 174 "Sound/MikMod/Module.hsc" #-}

getModuleWrap :: ModuleHandle -> IO Bool
getModuleWrap mod = decodeBool <$> ((\hsc_ptr -> peekByteOff hsc_ptr 272)) mod
{-# LINE 177 "Sound/MikMod/Module.hsc" #-}

-- | Set the restart position.
setModuleRepeatPosition :: ModuleHandle -> Int -> IO ()
setModuleRepeatPosition mod pos = ((\hsc_ptr -> pokeByteOff hsc_ptr 58)) mod (fromIntegral pos :: UBYTE)
{-# LINE 181 "Sound/MikMod/Module.hsc" #-}

getModuleRepeatPosition :: ModuleHandle -> IO Int
getModuleRepeatPosition mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 58)) mod :: IO UBYTE)
{-# LINE 184 "Sound/MikMod/Module.hsc" #-}

-- | Set the loop flag. False means only process forward loops or same-pattern
-- backward loops. Default is True, process all loops.
setModuleLoop :: ModuleHandle -> Bool -> IO ()
setModuleLoop mod flag = ((\hsc_ptr -> pokeByteOff hsc_ptr 276)) mod (encodeBool flag :: BOOL)
{-# LINE 189 "Sound/MikMod/Module.hsc" #-}

getModuleLoop :: ModuleHandle -> IO Bool
getModuleLoop mod = decodeBool <$> ((\hsc_ptr -> peekByteOff hsc_ptr 276)) mod
{-# LINE 192 "Sound/MikMod/Module.hsc" #-}

-- | Set the fadeout flag of the module. True means fade out. Default is False.
setModuleFadeout :: ModuleHandle -> Bool -> IO ()
setModuleFadeout mod flag = ((\hsc_ptr -> pokeByteOff hsc_ptr 280)) mod (encodeBool flag)
{-# LINE 196 "Sound/MikMod/Module.hsc" #-}

getModuleFadeout :: ModuleHandle -> IO Bool
getModuleFadeout mod = decodeBool <$> (((\hsc_ptr -> peekByteOff hsc_ptr 280)) mod :: IO BOOL)
{-# LINE 199 "Sound/MikMod/Module.hsc" #-}

-- | This value is added to the module tempo to define actual playback speed.
-- Default is zero.
setModuleRelativeSpeed :: ModuleHandle -> Int -> IO ()
setModuleRelativeSpeed mod s = ((\hsc_ptr -> pokeByteOff hsc_ptr 292)) mod (fromIntegral s :: SWORD)
{-# LINE 204 "Sound/MikMod/Module.hsc" #-}

getModuleRelativeSpeed :: ModuleHandle -> IO Int
getModuleRelativeSpeed mod = fromIntegral <$> (((\hsc_ptr -> peekByteOff hsc_ptr 292)) mod :: IO SWORD)
{-# LINE 207 "Sound/MikMod/Module.hsc" #-}