taffybar-2.1.0: src/System/Taffybar/Information/StreamInfo.hs
--------------------------------------------------------------------------------
-- |
-- Module : System.Taffybar.Information.StreamInfo
-- Copyright : (c) José A. Romero L.
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : José A. Romero L. <escherdragon@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- Generic code to poll any of the many data files maintained by the kernel in
-- POSIX systems. Provides methods for applying a custom parsing function to the
-- contents of the file and to calculate differentials across one or more values
-- provided via the file.
--
--------------------------------------------------------------------------------
module System.Taffybar.Information.StreamInfo
( getParsedInfo
, getLoad
, getAccLoad
, getTransfer
) where
import Control.Concurrent ( threadDelay )
import Data.IORef
import Data.Maybe ( fromMaybe )
-- | Apply the given parser function to the file under the given path to produce
-- a lookup map, then use the given selector as key to extract from it the
-- desired value.
getParsedInfo :: FilePath -> (String -> [(String, [a])]) -> String -> IO [a]
getParsedInfo path parser selector = do
file <- readFile path
length file `seq` return ()
return (fromMaybe [] $ lookup selector $ parser file)
truncVal :: (RealFloat a) => a -> a
truncVal v
| isNaN v || v < 0.0 = 0.0
| otherwise = v
-- | Convert the given list of Integer to a list of the ratios of each of its
-- elements against their sum.
toRatioList :: (Integral a, RealFloat b) => [a] -> [b]
toRatioList deltas = map truncVal ratios
where total = fromIntegral $ sum deltas
ratios = map ((/total) . fromIntegral) deltas
-- | Execute the given action twice with the given delay in-between and return
-- the difference between the two samples.
probe :: (Num a, RealFrac b) => IO [a] -> b -> IO [a]
probe action delay = do
a <- action
threadDelay $ round (delay * 1e6)
b <- action
return $ zipWith (-) b a
-- | Execute the given action once and return the difference between the
-- obtained sample and the one contained in the given IORef.
accProbe :: (Num a) => IO [a] -> IORef [a] -> IO [a]
accProbe action sample = do
a <- readIORef sample
b <- action
writeIORef sample b
return $ zipWith (-) b a
-- | Probe the given action and, interpreting the result as a variation in time,
-- return the speed of change of its values.
getTransfer :: (Integral a, RealFloat b) => b -> IO [a] -> IO [b]
getTransfer interval action = do
deltas <- probe action interval
return $ map (truncVal . (/interval) . fromIntegral) deltas
-- | Probe the given action and return the relative variation of each of the
-- obtained values against the whole, where the whole is calculated as the sum
-- of all the values in the probe.
getLoad :: (Integral a, RealFloat b) => b -> IO [a] -> IO [b]
getLoad interval action = toRatioList <$> probe action interval
-- | Similar to getLoad, but execute the given action only once and use the
-- given IORef to calculate the result and to save the current value, so it
-- can be reused in the next call.
getAccLoad :: (Integral a, RealFloat b) => IORef [a] -> IO [a] -> IO [b]
getAccLoad sample action = toRatioList <$> accProbe action sample