hmonitors/src/Monitors/Volume.hs

100 lines
2.9 KiB
Haskell

module Monitors.Volume (queryVolume) where
import Data.List
import Data.Maybe
import System.Process
import Text.Printf
import Text.Regex
import Text.Read
import qualified Data.Map as M
import Monitors.Common
mixer :: String
mixer = "Master"
icons :: M.Map String String
icons = M.map buildIcon $ M.fromList
[ ( "high" , 64125 )
, ( "low" , 64126 )
, ( "mid" , 64127 )
, ( "off" , 64128 )
, ( "mute" , 64605 )
]
data MixerData = MixerData
{ mute :: Bool
, vol :: Int
}
deriving Eq
getIcon :: MixerData -> String
getIcon x = fromMaybe (icons M.! def) $ M.lookup (iconKey x) icons
where
iconKey MixerData { mute = True } = "mute"
iconKey MixerData { vol = vol }
| vol >= 80 = "high"
| vol >= 10 && vol < 80 = "mid"
| vol < 10 = "low"
| otherwise = def
def = "high"
getColor :: MixerData -> String
getColor x = fromMaybe (colors M.! def) $ M.lookup (colorKey x) colors
where
colorKey MixerData { mute = True } = "inactive"
colorKey MixerData { vol = vol }
| vol > 110 = "red"
| vol > 100 && vol <= 110 = "yellow"
| vol > 70 && vol <= 100 = "green"
| vol > 0 && vol <= 70 = "blue"
| vol == 0 = "inactive"
| otherwise = def
def = "active"
getStatus :: MixerData -> String
getStatus x@MixerData { mute = mute, vol = vol } =
let
txtColor = if mute then colors M.! "inactive" else colors M.! "active"
icon = colorize (getColor x) (getIcon x)
txt = colorize txtColor $ show vol
in printf "%s %s" icon txt
parseMixerInfo :: String -> Maybe MixerData
parseMixerInfo = fmap fmtMixer . matchRegex regex
where
regex = mkRegex ".+: Playback [0-9]+ \\[([0-9]+)%\\] (\\[.+dB\\] )?\\[(on|off)\\]"
fmtMixer [volume,_,state] =
let
mute = case state of
"on" -> False
"off" -> True
_ -> False
vol = read volume
in MixerData { mute = mute, vol = vol }
fmtData :: MixerData -> String
fmtData = (separator ++ ) . getStatus
getMute :: IO Bool
getMute = parseMute <$> readProcess "/nix/store/ambq4n07zlax0lwz0v1yph85cph1sssk-pamixer-1.4/bin/pamixer" ["--get-mute"] ""
where
parseMute "true" = True
parseMute "false" = False
parseMute _ = False
getVol :: IO Int
getVol = parseVol <$> readProcess "pamixer" ["--get-volume"] ""
where
parseVol x = case readMaybe x of (Just vol) -> vol
Nothing -> 0
getInfo :: IO MixerData
getInfo = do
mute <- getMute
vol <- getVol
return $ MixerData { mute = mute, vol = vol }
queryVolume :: IO String
queryVolume = fmtData <$> getInfo