packages feed

riff-0.1.0.0: src/riff-structure.hs

module Main where

import Data.Riff
import Data.Riff.Operations

import System.Environment (getArgs)
import Data.List (intersperse)
import Control.Monad (when)
import Data.Char (chr)

main = do
   args <- getArgs
   case args of
      [] -> error "No filename provided to scan. Please give me a file."
      xs -> sequence_ . intersperse putNewline $ fmap processFile xs

processFile :: String -> IO ()
processFile filePath = do
   putStr "File: "
   print filePath
   withRiffFile filePath $ \potential -> case potential of
      Left (offset, error) -> putStrLn $ error ++ " (Offset: " ++ show offset ++ ")"
      Right riffFile -> printRiffFile startContext riffFile

data PrintContext = PrintContext
   { indentation :: Int
   , printValue :: Bool
   }
   deriving (Show)

startContext :: PrintContext
startContext = PrintContext 0 False

printRiffFile :: PrintContext -> RiffFile -> IO ()
printRiffFile context file@(RiffFile riffType formatType children) = do
   printWithIndent context (typeName riffType)
   putStrLn $ " (" ++ formatType ++ ") [" ++ showFileLength file ++ "]"
   mapM_ (printRiffChunk nextContext) children
   where
      nextContext = PrintContext
         { indentation = 1 + indentation context
         , printValue = False
         }

      typeName RIFF = "RIFF"
      typeName RIFX = "RIFX"

printRiffChunk :: PrintContext -> RiffChunk -> IO ()
printRiffChunk context chunk@(RiffChunkChild id value) = do
   printWithIndent context id
   putStr $ " [" ++ showLength chunk ++ "]"
   when (printValue context) $ do
      putStr ": "
      inQuotes (putStr . fmap (chr . fromIntegral) $ takeWhile (/= 0) value)
   putNewline
printRiffChunk context chunk@(RiffChunkParent typeName children) = do
   printWithIndent context "LIST"
   putStrLn $ " (" ++ typeName ++ ") [" ++ showLength chunk ++ "]"
   mapM_ (printRiffChunk nextContext) children
   where
      nextContext = PrintContext
         { indentation = 1 + indentation context
         , printValue = typeName == "INFO"
         }

showFileLength = show . calculateFileLength
showLength = show . calculateChunkLength

inQuotes :: IO () -> IO ()
inQuotes action = do
   putChar '"'
   action
   putChar '"'

printWithIndent :: PrintContext -> String -> IO ()
printWithIndent context value = do
   putStr . concat . take (indentation context) $ repeat "   "
   putStr value

putNewline = putStrLn ""