{-# LANGUAGE RecordWildCards, ApplicativeDo #-} import Options.Applicative import System.FilePath import System.FileLock import Data.Char import Data.Monoid import Data.List import Trivmix.Types data Options = Options { baseDirectory :: FilePath , targetDirectory :: FilePath , levelFile :: FilePath , adjustment :: Adjustment Level } optionParser :: Parser Options optionParser = do baseDirectory <- strOption $ mconcat [ long "base", metavar "DIRECTORY", showDefault , value "/dev/shm/mix" , help "Base directory" ] levelFile <- strOption $ mconcat [ long "level", short 'l', metavar "FILENAME", showDefault , value "level" , help "Filename of the level file" ] targetDirectory <- strArgument $ mconcat [ metavar "DIRECTORY" , help "Directory relative to ‘--base’ containing the level file" ] adjustment <- getAlt . mconcat $ map Alt [ Set <$> option auto (mconcat [ long "set", short 'o', metavar "LEVEL" , help "Overwrite the current level" ]) , Add <$> option auto (mconcat [ long "add", short 'a', metavar "LEVEL" , help "Add to the current level" ]) , Sub <$> option auto (mconcat [ long "sub", short 's', metavar "LEVEL" , help "Subtract from the current level" ]) , let adjMode = getAlt . mconcat $ map Alt [ flag' Add (mconcat [ long "inc", short 'i' , help "Increase level by a preset amount (see ‘--by’)" ]) , flag' Sub (mconcat [ long "dec", short 'd' , help "Decrease level by a preset amount (see ‘--by’)" ]) ] adjBy = option auto (mconcat [ long "by", short 'b', metavar "LEVEL", value (read "2.5dB"), showDefault , help "Value to increase/decrease level by when using ‘--inc’ or ‘--dec’" ]) in adjMode <*> adjBy ] return Options{..} main :: IO () main = execParser opts >>= adjmix where opts = info (helper <*> optionParser) $ mconcat [ progDesc "Adjust the level file of a trivmix" , header "Adjmix — A trivial interface to a trivial mixer" , fullDesc ] adjmix :: Options -> IO () adjmix Options{..} = withFileLock levelFile' Exclusive . const $ do oldLevel <- readFile levelFile' >>= readIO . stripSpace let newLevel = oldLevel `doAdjustment` adjustment writeFile levelFile' $ show newLevel ++ "\n" where levelFile' = baseDirectory targetDirectory levelFile stripSpace = dropWhile isSpace . dropWhileEnd isSpace