module MixerQuery ( mixerDevices, mixerChannels, setVol ) where import Data.List (isInfixOf, sort) import Data.List.Split (splitOn) import System.IO (FilePath) import System.Directory (getDirectoryContents) import System.Process (runInteractiveCommand) import GHC.IO.Handle (hGetContents) -- | Gets all available mixer devices on this system. mixerDevices :: IO [FilePath] mixerDevices = getDirectoryContents "/dev" >>= return . ("Default" : ) . map ((++) "/dev/") . sort . filter (isInfixOf "mixer") -- | Gets the channels from a mixer device. mixerChannels :: FilePath -> IO [(String, (Int, Int))] mixerChannels mixer = do (_, stdout, _, _) <- runInteractiveCommand $ command mixer hGetContents stdout >>= return . parseMixerLines . lines where command "Default" = "mixer" command mixer' = "mixer -f " ++ mixer' -- | Parses out the channel names and volumes from the output -- of the mixer command. parseMixerLines :: [String] -> [(String, (Int, Int))] parseMixerLines lines = [(line !! 1, parseLevels $ last line) | line <- map words $ filter (isInfixOf "Mixer ") lines] where parseLevels str = (\(x:y:_) -> (read x, read y)) $ splitOn ":" str -- | Sets the volume of a channel. setVol :: String -> String -> Int -> Int -> IO () setVol "Default" channel left right = setVolCmd ["mixer", channel, (show left) ++ ":" ++ (show right)] setVol mixer channel left right = setVolCmd ["mixer", "-f", mixer, channel, (show left) ++ ":" ++ (show right)] setVolCmd cmd = (runInteractiveCommand $ unwords cmd) >>= \_ -> return ()