    {-# LANGUAGE OverloadedStrings #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      : System.Taffybar.Information.Battery
    -- Copyright   : (c) Ivan A. Malison
    -- License     : BSD3-style (see LICENSE)
    --
    -- Maintainer  : Ivan A. Malison
    -- Stability   : unstable
    -- Portability : unportable
    --
    -- This module provides functions for querying battery information using the
    -- UPower dbus, as well as a "BroadcastChan" system for allowing multiple
    -- readers to receive 'BatteryState' updates without duplicating requests.
    -----------------------------------------------------------------------------
    module System.Taffybar.Information.Battery
      ( BatteryInfo(..)
      , BatteryState(..)
      , BatteryTechnology(..)
      , BatteryType(..)
      , module System.Taffybar.Information.Battery
      ) where

    import           BroadcastChan
    import           Control.Concurrent
    import           Control.Monad
    import           Control.Monad.IO.Class
    import           Control.Monad.Trans.Class
    import           Control.Monad.Trans.Except
    import           Control.Monad.Trans.Reader
    import           DBus
    import           DBus.Client
    import           DBus.Internal.Types (Serial(..))
    import qualified DBus.TH as DBus
    import           Data.Int
    import           Data.List
    import           Data.Map ( Map )
    import qualified Data.Map as M
    import           Data.Maybe
    import           Data.Text ( Text )
    import           Data.Word
    import           System.Log.Logger
    import           System.Taffybar.Context
    import           System.Taffybar.DBus.Client.Params
    import           System.Taffybar.DBus.Client.UPower
    import           System.Taffybar.DBus.Client.UPowerDevice
    import           System.Taffybar.Util

    batteryLogPath :: String
    batteryLogPath :: String
    batteryLogPath = String
    "System.Taffybar.Information.Battery"

    batteryLog
      :: MonadIO m
      => Priority -> String -> m ()
    batteryLog :: forall (m :: * -> *). MonadIO m => Priority -> String -> m ()
    batteryLog Priority
    priority = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (String -> IO ()) -> String -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Priority -> String -> IO ()
    logM String
    batteryLogPath Priority
    priority

    batteryLogF
      :: (MonadIO m, Show t)
      => Priority -> String -> t -> m ()
    batteryLogF :: forall (m :: * -> *) t.
    (MonadIO m, Show t) =>
    Priority -> String -> t -> m ()
    batteryLogF = String -> Priority -> String -> t -> m ()
    forall (m :: * -> *) t.
    (MonadIO m, Show t) =>
    String -> Priority -> String -> t -> m ()
    logPrintF String
    batteryLogPath

    -- | The prefix of name of battery devices path. UPower generates the object
    -- path as "battery" + "_" + basename of the sysfs object.
    batteryPrefix :: String
    batteryPrefix :: String
    batteryPrefix = ObjectPath -> String
    formatObjectPath ObjectPath
    uPowerBaseObjectPath String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    "/devices/battery_"

    -- | Determine if a power source is a battery.
    isBattery :: ObjectPath -> Bool
    isBattery :: ObjectPath -> Bool
    isBattery = String -> String -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    isPrefixOf String
    batteryPrefix (String -> Bool) -> (ObjectPath -> String) -> ObjectPath -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ObjectPath -> String
    formatObjectPath

    -- | A helper to read the variant contents of a dict with a default
    -- value.
    readDict :: (IsVariant a) => Map Text Variant -> Text -> a -> a
    readDict :: forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    key a
    dflt = a -> Maybe a -> a
    forall a. a -> Maybe a -> a
    fromMaybe a
    dflt (Maybe a -> a) -> Maybe a -> a
    forall a b. (a -> b) -> a -> b
    $ do
      Variant
    variant <- Text -> Map Text Variant -> Maybe Variant
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup Text
    key Map Text Variant
    dict
      Variant -> Maybe a
    forall a. IsVariant a => Variant -> Maybe a
    fromVariant Variant
    variant

    -- | Read the variant contents of a dict which is of an unknown integral type.
    readDictIntegral :: Map Text Variant -> Text -> Int32 -> Int
    readDictIntegral :: Map Text Variant -> Text -> Int32 -> Int
    readDictIntegral Map Text Variant
    dict Text
    key Int32
    dflt = Int -> Maybe Int -> Int
    forall a. a -> Maybe a -> a
    fromMaybe (Int32 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int32
    dflt) (Maybe Int -> Int) -> Maybe Int -> Int
    forall a b. (a -> b) -> a -> b
    $ do
      Variant
    v <- Text -> Map Text Variant -> Maybe Variant
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup Text
    key Map Text Variant
    dict
      case Variant -> Type
    variantType Variant
    v of
        Type
    TypeWord8   -> Int -> Maybe Int
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Int -> Maybe Int) -> Int -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Variant -> Word8
    forall a. (Num a, IsVariant a) => Variant -> a
    f Variant
    v :: Word8)
        Type
    TypeWord16  -> Int -> Maybe Int
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Int -> Maybe Int) -> Int -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ Word16 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Variant -> Word16
    forall a. (Num a, IsVariant a) => Variant -> a
    f Variant
    v :: Word16)
        Type
    TypeWord32  -> Int -> Maybe Int
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Int -> Maybe Int) -> Int -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ Word32 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Variant -> Word32
    forall a. (Num a, IsVariant a) => Variant -> a
    f Variant
    v :: Word32)
        Type
    TypeWord64  -> Int -> Maybe Int
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Int -> Maybe Int) -> Int -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Variant -> Word64
    forall a. (Num a, IsVariant a) => Variant -> a
    f Variant
    v :: Word64)
        Type
    TypeInt16   -> Int -> Maybe Int
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Int -> Maybe Int) -> Int -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ Int16 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Variant -> Int16
    forall a. (Num a, IsVariant a) => Variant -> a
    f Variant
    v :: Int16)
        Type
    TypeInt32   -> Int -> Maybe Int
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Int -> Maybe Int) -> Int -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ Int32 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Variant -> Int32
    forall a. (Num a, IsVariant a) => Variant -> a
    f Variant
    v :: Int32)
        Type
    TypeInt64   -> Int -> Maybe Int
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Int -> Maybe Int) -> Int -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ Int64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Variant -> Int64
    forall a. (Num a, IsVariant a) => Variant -> a
    f Variant
    v :: Int64)
        Type
    _           -> Maybe Int
    forall a. Maybe a
    Nothing
      where
        f :: (Num a, IsVariant a) => Variant -> a
        f :: forall a. (Num a, IsVariant a) => Variant -> a
    f = a -> Maybe a -> a
    forall a. a -> Maybe a -> a
    fromMaybe (Int32 -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int32
    dflt) (Maybe a -> a) -> (Variant -> Maybe a) -> Variant -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Variant -> Maybe a
    forall a. IsVariant a => Variant -> Maybe a
    fromVariant

    -- XXX: Remove this once it is exposed in haskell-dbus
    dummyMethodError :: MethodError
    dummyMethodError :: MethodError
    dummyMethodError = Serial -> ErrorName -> MethodError
    methodError (Word32 -> Serial
    Serial Word32
    1) (ErrorName -> MethodError) -> ErrorName -> MethodError
    forall a b. (a -> b) -> a -> b
    $ String -> ErrorName
    errorName_ String
    "org.ClientTypeMismatch"

    -- | Query the UPower daemon about information on a specific battery.
    -- If some fields are not actually present, they may have bogus values
    -- here.  Don't bet anything critical on it.
    getBatteryInfo :: ObjectPath -> TaffyIO (Either MethodError BatteryInfo)
    getBatteryInfo :: ObjectPath -> TaffyIO (Either MethodError BatteryInfo)
    getBatteryInfo ObjectPath
    battPath = (Context -> Client) -> ReaderT Context IO Client
    forall (m :: * -> *) r a. Monad m => (r -> a) -> ReaderT r m a
    asks Context -> Client
    systemDBusClient ReaderT Context IO Client
    -> (Client -> TaffyIO (Either MethodError BatteryInfo))
    -> TaffyIO (Either MethodError BatteryInfo)
    forall a b.
    ReaderT Context IO a
    -> (a -> ReaderT Context IO b) -> ReaderT Context IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \Client
    client -> IO (Either MethodError BatteryInfo)
    -> TaffyIO (Either MethodError BatteryInfo)
    forall (m :: * -> *) a. Monad m => m a -> ReaderT Context m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (IO (Either MethodError BatteryInfo)
     -> TaffyIO (Either MethodError BatteryInfo))
    -> IO (Either MethodError BatteryInfo)
    -> TaffyIO (Either MethodError BatteryInfo)
    forall a b. (a -> b) -> a -> b
    $ ExceptT MethodError IO BatteryInfo
    -> IO (Either MethodError BatteryInfo)
    forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
    runExceptT (ExceptT MethodError IO BatteryInfo
     -> IO (Either MethodError BatteryInfo))
    -> ExceptT MethodError IO BatteryInfo
    -> IO (Either MethodError BatteryInfo)
    forall a b. (a -> b) -> a -> b
    $ do
      MethodReturn
    reply <- IO (Either MethodError MethodReturn)
    -> ExceptT MethodError IO MethodReturn
    forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
    ExceptT (IO (Either MethodError MethodReturn)
     -> ExceptT MethodError IO MethodReturn)
    -> IO (Either MethodError MethodReturn)
    -> ExceptT MethodError IO MethodReturn
    forall a b. (a -> b) -> a -> b
    $ Client -> MethodCall -> IO (Either MethodError MethodReturn)
    getAllProperties Client
    client (MethodCall -> IO (Either MethodError MethodReturn))
    -> MethodCall -> IO (Either MethodError MethodReturn)
    forall a b. (a -> b) -> a -> b
    $
               (ObjectPath -> InterfaceName -> MemberName -> MethodCall
    methodCall ObjectPath
    battPath InterfaceName
    uPowerDeviceInterfaceName MemberName
    "FakeMethod")
               { methodCallDestination :: Maybe BusName
    methodCallDestination = BusName -> Maybe BusName
    forall a. a -> Maybe a
    Just BusName
    uPowerBusName }
      Map Text Variant
    dict <- IO (Either MethodError (Map Text Variant))
    -> ExceptT MethodError IO (Map Text Variant)
    forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
    ExceptT (IO (Either MethodError (Map Text Variant))
     -> ExceptT MethodError IO (Map Text Variant))
    -> IO (Either MethodError (Map Text Variant))
    -> ExceptT MethodError IO (Map Text Variant)
    forall a b. (a -> b) -> a -> b
    $ Either MethodError (Map Text Variant)
    -> IO (Either MethodError (Map Text Variant))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either MethodError (Map Text Variant)
     -> IO (Either MethodError (Map Text Variant)))
    -> Either MethodError (Map Text Variant)
    -> IO (Either MethodError (Map Text Variant))
    forall a b. (a -> b) -> a -> b
    $ MethodError
    -> Maybe (Map Text Variant)
    -> Either MethodError (Map Text Variant)
    forall b a. b -> Maybe a -> Either b a
    maybeToEither MethodError
    dummyMethodError (Maybe (Map Text Variant) -> Either MethodError (Map Text Variant))
    -> Maybe (Map Text Variant)
    -> Either MethodError (Map Text Variant)
    forall a b. (a -> b) -> a -> b
    $
             [Variant] -> Maybe Variant
    forall a. [a] -> Maybe a
    listToMaybe (MethodReturn -> [Variant]
    methodReturnBody MethodReturn
    reply) Maybe Variant
    -> (Variant -> Maybe (Map Text Variant))
    -> Maybe (Map Text Variant)
    forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Variant -> Maybe (Map Text Variant)
    forall a. IsVariant a => Variant -> Maybe a
    fromVariant
      BatteryInfo -> ExceptT MethodError IO BatteryInfo
    forall a. a -> ExceptT MethodError IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (BatteryInfo -> ExceptT MethodError IO BatteryInfo)
    -> BatteryInfo -> ExceptT MethodError IO BatteryInfo
    forall a b. (a -> b) -> a -> b
    $ Map Text Variant -> BatteryInfo
    infoMapToBatteryInfo Map Text Variant
    dict

    infoMapToBatteryInfo :: Map Text Variant -> BatteryInfo
    infoMapToBatteryInfo :: Map Text Variant -> BatteryInfo
    infoMapToBatteryInfo Map Text Variant
    dict =
        BatteryInfo
          { batteryNativePath :: String
    batteryNativePath = Map Text Variant -> Text -> String -> String
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "NativePath" String
    ""
          , batteryVendor :: String
    batteryVendor = Map Text Variant -> Text -> String -> String
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Vendor" String
    ""
          , batteryModel :: String
    batteryModel = Map Text Variant -> Text -> String -> String
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Model" String
    ""
          , batterySerial :: String
    batterySerial = Map Text Variant -> Text -> String -> String
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Serial" String
    ""
          , batteryType :: BatteryType
    batteryType = Int -> BatteryType
    forall a. Enum a => Int -> a
    toEnum (Int -> BatteryType) -> Int -> BatteryType
    forall a b. (a -> b) -> a -> b
    $ Int -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> Int) -> Int -> Int
    forall a b. (a -> b) -> a -> b
    $ Map Text Variant -> Text -> Int32 -> Int
    readDictIntegral Map Text Variant
    dict Text
    "Type" Int32
    0
          , batteryPowerSupply :: Bool
    batteryPowerSupply = Map Text Variant -> Text -> Bool -> Bool
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "PowerSupply" Bool
    False
          , batteryHasHistory :: Bool
    batteryHasHistory = Map Text Variant -> Text -> Bool -> Bool
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "HasHistory" Bool
    False
          , batteryHasStatistics :: Bool
    batteryHasStatistics = Map Text Variant -> Text -> Bool -> Bool
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "HasStatistics" Bool
    False
          , batteryOnline :: Bool
    batteryOnline = Map Text Variant -> Text -> Bool -> Bool
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Online" Bool
    False
          , batteryEnergy :: Double
    batteryEnergy = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Energy" Double
    0.0
          , batteryEnergyEmpty :: Double
    batteryEnergyEmpty = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "EnergyEmpty" Double
    0.0
          , batteryEnergyFull :: Double
    batteryEnergyFull = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "EnergyFull" Double
    0.0
          , batteryEnergyFullDesign :: Double
    batteryEnergyFullDesign = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "EnergyFullDesign" Double
    0.0
          , batteryEnergyRate :: Double
    batteryEnergyRate = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "EnergyRate" Double
    0.0
          , batteryVoltage :: Double
    batteryVoltage = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Voltage" Double
    0.0
          , batteryTimeToEmpty :: Int64
    batteryTimeToEmpty = Map Text Variant -> Text -> Int64 -> Int64
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "TimeToEmpty" Int64
    0
          , batteryTimeToFull :: Int64
    batteryTimeToFull = Map Text Variant -> Text -> Int64 -> Int64
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "TimeToFull" Int64
    0
          , batteryPercentage :: Double
    batteryPercentage = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Percentage" Double
    0.0
          , batteryIsPresent :: Bool
    batteryIsPresent = Map Text Variant -> Text -> Bool -> Bool
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "IsPresent" Bool
    False
          , batteryState :: BatteryState
    batteryState = Int -> BatteryState
    forall a. Enum a => Int -> a
    toEnum (Int -> BatteryState) -> Int -> BatteryState
    forall a b. (a -> b) -> a -> b
    $ Map Text Variant -> Text -> Int32 -> Int
    readDictIntegral Map Text Variant
    dict Text
    "State" Int32
    0
          , batteryIsRechargeable :: Bool
    batteryIsRechargeable = Map Text Variant -> Text -> Bool -> Bool
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "IsRechargable" Bool
    True
          , batteryCapacity :: Double
    batteryCapacity = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Capacity" Double
    0.0
          , batteryTechnology :: BatteryTechnology
    batteryTechnology =
              Int -> BatteryTechnology
    forall a. Enum a => Int -> a
    toEnum (Int -> BatteryTechnology) -> Int -> BatteryTechnology
    forall a b. (a -> b) -> a -> b
    $ Int -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> Int) -> Int -> Int
    forall a b. (a -> b) -> a -> b
    $ Map Text Variant -> Text -> Int32 -> Int
    readDictIntegral Map Text Variant
    dict Text
    "Technology" Int32
    0
          , batteryUpdateTime :: Word64
    batteryUpdateTime = Map Text Variant -> Text -> Word64 -> Word64
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "UpdateTime" Word64
    0
          , batteryLuminosity :: Double
    batteryLuminosity = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Luminosity" Double
    0.0
          , batteryTemperature :: Double
    batteryTemperature = Map Text Variant -> Text -> Double -> Double
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "Temperature" Double
    0.0
          , batteryWarningLevel :: Word32
    batteryWarningLevel = Map Text Variant -> Text -> Word32 -> Word32
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "WarningLevel" Word32
    0
          , batteryBatteryLevel :: Word32
    batteryBatteryLevel = Map Text Variant -> Text -> Word32 -> Word32
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "BatteryLevel" Word32
    0
          , batteryIconName :: String
    batteryIconName = Map Text Variant -> Text -> String -> String
    forall a. IsVariant a => Map Text Variant -> Text -> a -> a
    readDict Map Text Variant
    dict Text
    "IconName" String
    ""
          }

    getBatteryPaths :: TaffyIO (Either MethodError [ObjectPath])
    getBatteryPaths :: TaffyIO (Either MethodError [ObjectPath])
    getBatteryPaths = do
      Client
    client <- (Context -> Client) -> ReaderT Context IO Client
    forall (m :: * -> *) r a. Monad m => (r -> a) -> ReaderT r m a
    asks Context -> Client
    systemDBusClient
      IO (Either MethodError [ObjectPath])
    -> TaffyIO (Either MethodError [ObjectPath])
    forall a. IO a -> ReaderT Context IO a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Either MethodError [ObjectPath])
     -> TaffyIO (Either MethodError [ObjectPath]))
    -> IO (Either MethodError [ObjectPath])
    -> TaffyIO (Either MethodError [ObjectPath])
    forall a b. (a -> b) -> a -> b
    $ ExceptT MethodError IO [ObjectPath]
    -> IO (Either MethodError [ObjectPath])
    forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
    runExceptT (ExceptT MethodError IO [ObjectPath]
     -> IO (Either MethodError [ObjectPath]))
    -> ExceptT MethodError IO [ObjectPath]
    -> IO (Either MethodError [ObjectPath])
    forall a b. (a -> b) -> a -> b
    $ do
        [ObjectPath]
    paths <- IO (Either MethodError [ObjectPath])
    -> ExceptT MethodError IO [ObjectPath]
    forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
    ExceptT (IO (Either MethodError [ObjectPath])
     -> ExceptT MethodError IO [ObjectPath])
    -> IO (Either MethodError [ObjectPath])
    -> ExceptT MethodError IO [ObjectPath]
    forall a b. (a -> b) -> a -> b
    $ Client -> IO (Either MethodError [ObjectPath])
    enumerateDevices Client
    client
        [ObjectPath] -> ExceptT MethodError IO [ObjectPath]
    forall a. a -> ExceptT MethodError IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([ObjectPath] -> ExceptT MethodError IO [ObjectPath])
    -> [ObjectPath] -> ExceptT MethodError IO [ObjectPath]
    forall a b. (a -> b) -> a -> b
    $ (ObjectPath -> Bool) -> [ObjectPath] -> [ObjectPath]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ObjectPath -> Bool
    isBattery [ObjectPath]
    paths

    newtype DisplayBatteryChanVar =
      DisplayBatteryChanVar (BroadcastChan In BatteryInfo, MVar BatteryInfo)

    getDisplayBatteryInfo :: TaffyIO BatteryInfo
    getDisplayBatteryInfo :: TaffyIO BatteryInfo
    getDisplayBatteryInfo = do
      DisplayBatteryChanVar (BroadcastChan In BatteryInfo
    _, MVar BatteryInfo
    theVar) <- TaffyIO DisplayBatteryChanVar
    getDisplayBatteryChanVar
      IO BatteryInfo -> TaffyIO BatteryInfo
    forall (m :: * -> *) a. Monad m => m a -> ReaderT Context m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (IO BatteryInfo -> TaffyIO BatteryInfo)
    -> IO BatteryInfo -> TaffyIO BatteryInfo
    forall a b. (a -> b) -> a -> b
    $ MVar BatteryInfo -> IO BatteryInfo
    forall a. MVar a -> IO a
    readMVar MVar BatteryInfo
    theVar

    defaultMonitorDisplayBatteryProperties :: [String]
    defaultMonitorDisplayBatteryProperties :: [String]
    defaultMonitorDisplayBatteryProperties = [ String
    "IconName", String
    "State", String
    "Percentage" ]

    -- | Start the monitoring of the display battery, and setup the associated
    -- channel and mvar for the current state.
    setupDisplayBatteryChanVar :: [String] -> TaffyIO DisplayBatteryChanVar
    setupDisplayBatteryChanVar :: [String] -> TaffyIO DisplayBatteryChanVar
    setupDisplayBatteryChanVar [String]
    properties = TaffyIO DisplayBatteryChanVar -> TaffyIO DisplayBatteryChanVar
    forall t. Typeable t => Taffy IO t -> Taffy IO t
    getStateDefault (TaffyIO DisplayBatteryChanVar -> TaffyIO DisplayBatteryChanVar)
    -> TaffyIO DisplayBatteryChanVar -> TaffyIO DisplayBatteryChanVar
    forall a b. (a -> b) -> a -> b
    $
      (BroadcastChan In BatteryInfo, MVar BatteryInfo)
    -> DisplayBatteryChanVar
    DisplayBatteryChanVar ((BroadcastChan In BatteryInfo, MVar BatteryInfo)
     -> DisplayBatteryChanVar)
    -> ReaderT
         Context IO (BroadcastChan In BatteryInfo, MVar BatteryInfo)
    -> TaffyIO DisplayBatteryChanVar
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> [String]
    -> ReaderT
         Context IO (BroadcastChan In BatteryInfo, MVar BatteryInfo)
    monitorDisplayBattery [String]
    properties

    getDisplayBatteryChanVar :: TaffyIO DisplayBatteryChanVar
    getDisplayBatteryChanVar :: TaffyIO DisplayBatteryChanVar
    getDisplayBatteryChanVar =
      [String] -> TaffyIO DisplayBatteryChanVar
    setupDisplayBatteryChanVar [String]
    defaultMonitorDisplayBatteryProperties

    getDisplayBatteryChan :: TaffyIO (BroadcastChan In BatteryInfo)
    getDisplayBatteryChan :: TaffyIO (BroadcastChan In BatteryInfo)
    getDisplayBatteryChan = do
      DisplayBatteryChanVar (BroadcastChan In BatteryInfo
    chan, MVar BatteryInfo
    _) <- TaffyIO DisplayBatteryChanVar
    getDisplayBatteryChanVar
      BroadcastChan In BatteryInfo
    -> TaffyIO (BroadcastChan In BatteryInfo)
    forall a. a -> ReaderT Context IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return BroadcastChan In BatteryInfo
    chan

    updateBatteryInfo
      :: BroadcastChan In BatteryInfo
      -> MVar BatteryInfo
      -> ObjectPath
      -> TaffyIO ()
    updateBatteryInfo :: BroadcastChan In BatteryInfo
    -> MVar BatteryInfo -> ObjectPath -> TaffyIO ()
    updateBatteryInfo BroadcastChan In BatteryInfo
    chan MVar BatteryInfo
    var ObjectPath
    path =
      ObjectPath -> TaffyIO (Either MethodError BatteryInfo)
    getBatteryInfo ObjectPath
    path TaffyIO (Either MethodError BatteryInfo)
    -> (Either MethodError BatteryInfo -> TaffyIO ()) -> TaffyIO ()
    forall a b.
    ReaderT Context IO a
    -> (a -> ReaderT Context IO b) -> ReaderT Context IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= IO () -> TaffyIO ()
    forall (m :: * -> *) a. Monad m => m a -> ReaderT Context m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (IO () -> TaffyIO ())
    -> (Either MethodError BatteryInfo -> IO ())
    -> Either MethodError BatteryInfo
    -> TaffyIO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (MethodError -> IO ())
    -> (BatteryInfo -> IO ())
    -> Either MethodError BatteryInfo
    -> IO ()
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either MethodError -> IO ()
    warnOfFailure BatteryInfo -> IO ()
    doWrites
      where
        doWrites :: BatteryInfo -> IO ()
    doWrites BatteryInfo
    info =
            Priority -> String -> BatteryInfo -> IO ()
    forall (m :: * -> *) t.
    (MonadIO m, Show t) =>
    Priority -> String -> t -> m ()
    batteryLogF Priority
    DEBUG String
    "Writing info %s" BatteryInfo
    info IO () -> IO BatteryInfo -> IO BatteryInfo
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >>
            MVar BatteryInfo -> BatteryInfo -> IO BatteryInfo
    forall a. MVar a -> a -> IO a
    swapMVar MVar BatteryInfo
    var BatteryInfo
    info IO BatteryInfo -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> IO Bool -> IO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (BroadcastChan In BatteryInfo -> BatteryInfo -> IO Bool
    forall (m :: * -> *) a.
    MonadIO m =>
    BroadcastChan In a -> a -> m Bool
    writeBChan BroadcastChan In BatteryInfo
    chan BatteryInfo
    info)
        warnOfFailure :: MethodError -> IO ()
    warnOfFailure = Priority -> String -> MethodError -> IO ()
    forall (m :: * -> *) t.
    (MonadIO m, Show t) =>
    Priority -> String -> t -> m ()
    batteryLogF Priority
    WARNING String
    "Failed to update battery info %s"

    registerForAnyUPowerPropertiesChanged
      :: (Signal -> String -> Map String Variant -> [String] -> IO ())
      -> ReaderT Context IO SignalHandler
    registerForAnyUPowerPropertiesChanged :: (Signal -> String -> Map String Variant -> [String] -> IO ())
    -> ReaderT Context IO SignalHandler
    registerForAnyUPowerPropertiesChanged = [String]
    -> (Signal -> String -> Map String Variant -> [String] -> IO ())
    -> ReaderT Context IO SignalHandler
    registerForUPowerPropertyChanges []

    registerForUPowerPropertyChanges
      :: [String]
      -> (Signal -> String -> Map String Variant -> [String] -> IO ())
      -> ReaderT Context IO SignalHandler
    registerForUPowerPropertyChanges :: [String]
    -> (Signal -> String -> Map String Variant -> [String] -> IO ())
    -> ReaderT Context IO SignalHandler
    registerForUPowerPropertyChanges [String]
    properties Signal -> String -> Map String Variant -> [String] -> IO ()
    signalHandler = do
      Client
    client <- (Context -> Client) -> ReaderT Context IO Client
    forall (m :: * -> *) r a. Monad m => (r -> a) -> ReaderT r m a
    asks Context -> Client
    systemDBusClient
      IO SignalHandler -> ReaderT Context IO SignalHandler
    forall (m :: * -> *) a. Monad m => m a -> ReaderT Context m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (IO SignalHandler -> ReaderT Context IO SignalHandler)
    -> IO SignalHandler -> ReaderT Context IO SignalHandler
    forall a b. (a -> b) -> a -> b
    $ Client
    -> MatchRule
    -> (Signal -> String -> Map String Variant -> [String] -> IO ())
    -> IO SignalHandler
    DBus.registerForPropertiesChanged
          Client
    client
          MatchRule
    matchAny { matchInterface :: Maybe InterfaceName
    matchInterface = InterfaceName -> Maybe InterfaceName
    forall a. a -> Maybe a
    Just InterfaceName
    uPowerDeviceInterfaceName }
          Signal -> String -> Map String Variant -> [String] -> IO ()
    handleIfPropertyMatches
      where handleIfPropertyMatches :: Signal -> String -> Map String Variant -> [String] -> IO ()
    handleIfPropertyMatches Signal
    rawSignal String
    n Map String Variant
    propertiesMap [String]
    l =
              let propertyPresent :: String -> Bool
    propertyPresent String
    prop = Maybe Variant -> Bool
    forall a. Maybe a -> Bool
    isJust (Maybe Variant -> Bool) -> Maybe Variant -> Bool
    forall a b. (a -> b) -> a -> b
    $ String -> Map String Variant -> Maybe Variant
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup String
    prop Map String Variant
    propertiesMap
              in Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when ((String -> Bool) -> [String] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any String -> Bool
    propertyPresent [String]
    properties Bool -> Bool -> Bool
    || [String] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [String]
    properties) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
                 Signal -> String -> Map String Variant -> [String] -> IO ()
    signalHandler Signal
    rawSignal String
    n Map String Variant
    propertiesMap [String]
    l

    -- | Monitor the DisplayDevice for changes, writing a new "BatteryInfo" object
    -- to returned "MVar" and "Chan" objects
    monitorDisplayBattery ::
      [String] -> TaffyIO (BroadcastChan In BatteryInfo, MVar BatteryInfo)
    monitorDisplayBattery :: [String]
    -> ReaderT
         Context IO (BroadcastChan In BatteryInfo, MVar BatteryInfo)
    monitorDisplayBattery [String]
    propertiesToMonitor = do
      IO () -> TaffyIO ()
    forall (m :: * -> *) a. Monad m => m a -> ReaderT Context m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (IO () -> TaffyIO ()) -> IO () -> TaffyIO ()
    forall a b. (a -> b) -> a -> b
    $ Priority -> String -> IO ()
    forall (m :: * -> *). MonadIO m => Priority -> String -> m ()
    batteryLog Priority
    DEBUG String
    "Starting Battery Monitor"
      Client
    client <- (Context -> Client) -> ReaderT Context IO Client
    forall (m :: * -> *) r a. Monad m => (r -> a) -> ReaderT r m a
    asks Context -> Client
    systemDBusClient
      MVar BatteryInfo
    infoVar <- IO (MVar BatteryInfo) -> ReaderT Context IO (MVar BatteryInfo)
    forall (m :: * -> *) a. Monad m => m a -> ReaderT Context m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (IO (MVar BatteryInfo) -> ReaderT Context IO (MVar BatteryInfo))
    -> IO (MVar BatteryInfo) -> ReaderT Context IO (MVar BatteryInfo)
    forall a b. (a -> b) -> a -> b
    $ BatteryInfo -> IO (MVar BatteryInfo)
    forall a. a -> IO (MVar a)
    newMVar (BatteryInfo -> IO (MVar BatteryInfo))
    -> BatteryInfo -> IO (MVar BatteryInfo)
    forall a b. (a -> b) -> a -> b
    $ Map Text Variant -> BatteryInfo
    infoMapToBatteryInfo Map Text Variant
    forall k a. Map k a
    M.empty
      BroadcastChan In BatteryInfo
    chan <- TaffyIO (BroadcastChan In BatteryInfo)
    forall (m :: * -> *) a. MonadIO m => m (BroadcastChan In a)
    newBroadcastChan
      TaffyIO () -> TaffyIO ()
    forall r. ReaderT r IO () -> ReaderT r IO ()
    taffyFork (TaffyIO () -> TaffyIO ()) -> TaffyIO () -> TaffyIO ()
    forall a b. (a -> b) -> a -> b
    $ do
        Context
    ctx <- ReaderT Context IO Context
    forall (m :: * -> *) r. Monad m => ReaderT r m r
    ask
        let warnOfFailedGetDevice :: t -> m b
    warnOfFailedGetDevice t
    err =
              Priority -> String -> t -> m ()
    forall (m :: * -> *) t.
    (MonadIO m, Show t) =>
    Priority -> String -> t -> m ()
    batteryLogF Priority
    WARNING String
    "Failure getting DisplayBattery: %s" t
    err m () -> m b -> m b
    forall a b. m a -> m b -> m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >>
              b -> m b
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return b
    "/org/freedesktop/UPower/devices/DisplayDevice"
        ObjectPath
    displayPath <- IO ObjectPath -> ReaderT Context IO ObjectPath
    forall (m :: * -> *) a. Monad m => m a -> ReaderT Context m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (IO ObjectPath -> ReaderT Context IO ObjectPath)
    -> IO ObjectPath -> ReaderT Context IO ObjectPath
    forall a b. (a -> b) -> a -> b
    $ Client -> IO (Either MethodError ObjectPath)
    getDisplayDevice Client
    client IO (Either MethodError ObjectPath)
    -> (Either MethodError ObjectPath -> IO ObjectPath)
    -> IO ObjectPath
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
                       (MethodError -> IO ObjectPath)
    -> (ObjectPath -> IO ObjectPath)
    -> Either MethodError ObjectPath
    -> IO ObjectPath
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either MethodError -> IO ObjectPath
    forall {m :: * -> *} {t} {b}.
    (MonadIO m, Show t, IsString b) =>
    t -> m b
    warnOfFailedGetDevice ObjectPath -> IO ObjectPath
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return
        let doUpdate :: TaffyIO ()
    doUpdate = BroadcastChan In BatteryInfo
    -> MVar BatteryInfo -> ObjectPath -> TaffyIO ()
    updateBatteryInfo BroadcastChan In BatteryInfo
    chan MVar BatteryInfo
    infoVar ObjectPath
    displayPath
            signalCallback :: Signal -> String -> Map String Variant -> [String] -> IO ()
    signalCallback Signal
    _ String
    _ Map String Variant
    changedProps [String]
    _ =
              do
                Priority -> String -> Map String Variant -> IO ()
    forall (m :: * -> *) t.
    (MonadIO m, Show t) =>
    Priority -> String -> t -> m ()
    batteryLogF Priority
    DEBUG String
    "Battery changed properties: %s" Map String Variant
    changedProps
                TaffyIO () -> Context -> IO ()
    forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
    runReaderT TaffyIO ()
    doUpdate Context
    ctx
        SignalHandler
    _ <- [String]
    -> (Signal -> String -> Map String Variant -> [String] -> IO ())
    -> ReaderT Context IO SignalHandler
    registerForUPowerPropertyChanges [String]
    propertiesToMonitor Signal -> String -> Map String Variant -> [String] -> IO ()
    signalCallback
        TaffyIO ()
    doUpdate
        () -> TaffyIO ()
    forall a. a -> ReaderT Context IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
      (BroadcastChan In BatteryInfo, MVar BatteryInfo)
    -> ReaderT
         Context IO (BroadcastChan In BatteryInfo, MVar BatteryInfo)
    forall a. a -> ReaderT Context IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (BroadcastChan In BatteryInfo
    chan, MVar BatteryInfo
    infoVar)

    -- | Call "refreshAllBatteries" whenever the BatteryInfo for the DisplayDevice
    -- is updated. This handles cases where there is a race between the signal that
    -- something is updated and the update actually being visible. See
    -- https://github.com/taffybar/taffybar/issues/330 for more details.
    refreshBatteriesOnPropChange :: TaffyIO ()
    refreshBatteriesOnPropChange :: TaffyIO ()
    refreshBatteriesOnPropChange = ReaderT Context IO Context
    forall (m :: * -> *) r. Monad m => ReaderT r m r
    ask ReaderT Context IO Context -> (Context -> TaffyIO ()) -> TaffyIO ()
    forall a b.
    ReaderT Context IO a
    -> (a -> ReaderT Context IO b) -> ReaderT Context IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \Context
    ctx ->
      let updateIfRealChange :: Signal -> String -> Map String Variant -> [String] -> IO ()
    updateIfRealChange Signal
    _ String
    _ Map String Variant
    changedProps [String]
    _ =
            (TaffyIO () -> Context -> IO ()) -> Context -> TaffyIO () -> IO ()
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip TaffyIO () -> Context -> IO ()
    forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
    runReaderT Context
    ctx (TaffyIO () -> IO ()) -> TaffyIO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
                 Bool -> TaffyIO () -> TaffyIO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (((String, Variant) -> Bool) -> [(String, Variant)] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any ((String -> [String] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` [String
    "UpdateTime", String
    "Voltage"]) (String -> Bool)
    -> ((String, Variant) -> String) -> (String, Variant) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String, Variant) -> String
    forall a b. (a, b) -> a
    fst) ([(String, Variant)] -> Bool) -> [(String, Variant)] -> Bool
    forall a b. (a -> b) -> a -> b
    $
                           Map String Variant -> [(String, Variant)]
    forall k a. Map k a -> [(k, a)]
    M.toList Map String Variant
    changedProps) (TaffyIO () -> TaffyIO ()) -> TaffyIO () -> TaffyIO ()
    forall a b. (a -> b) -> a -> b
    $
                      IO () -> TaffyIO ()
    forall (m :: * -> *) a. Monad m => m a -> ReaderT Context m a
    forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
    (MonadTrans t, Monad m) =>
    m a -> t m a
    lift (Int -> IO ()
    threadDelay Int
    1000000) TaffyIO () -> TaffyIO () -> TaffyIO ()
    forall a b.
    ReaderT Context IO a
    -> ReaderT Context IO b -> ReaderT Context IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> TaffyIO ()
    refreshAllBatteries
      in ReaderT Context IO SignalHandler -> TaffyIO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (ReaderT Context IO SignalHandler -> TaffyIO ())
    -> ReaderT Context IO SignalHandler -> TaffyIO ()
    forall a b. (a -> b) -> a -> b
    $ (Signal -> String -> Map String Variant -> [String] -> IO ())
    -> ReaderT Context IO SignalHandler
    registerForAnyUPowerPropertiesChanged Signal -> String -> Map String Variant -> [String] -> IO ()
    updateIfRealChange

    -- | Request a refresh of all UPower batteries. This is only needed if UPower's
    -- refresh mechanism is not working properly.
    refreshAllBatteries :: TaffyIO ()
    refreshAllBatteries :: TaffyIO ()
    refreshAllBatteries = do
      Client
    client <- (Context -> Client) -> ReaderT Context IO Client
    forall (m :: * -> *) r a. Monad m => (r -> a) -> ReaderT r m a
    asks Context -> Client
    systemDBusClient
      let doRefresh :: ObjectPath -> IO (Either MethodError ())
    doRefresh ObjectPath
    path =
            Priority -> String -> ObjectPath -> IO ()
    forall (m :: * -> *) t.
    (MonadIO m, Show t) =>
    Priority -> String -> t -> m ()
    batteryLogF Priority
    DEBUG String
    "Refreshing battery: %s" ObjectPath
    path IO () -> IO (Either MethodError ()) -> IO (Either MethodError ())
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Client -> ObjectPath -> IO (Either MethodError ())
    refresh Client
    client ObjectPath
    path
      Either MethodError [Either MethodError ()]
    eerror <- ExceptT MethodError (ReaderT Context IO) [Either MethodError ()]
    -> ReaderT Context IO (Either MethodError [Either MethodError ()])
    forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
    runExceptT (ExceptT MethodError (ReaderT Context IO) [Either MethodError ()]
     -> ReaderT Context IO (Either MethodError [Either MethodError ()]))
    -> ExceptT MethodError (ReaderT Context IO) [Either MethodError ()]
    -> ReaderT Context IO (Either MethodError [Either MethodError ()])
    forall a b. (a -> b) -> a -> b
    $ TaffyIO (Either MethodError [ObjectPath])
    -> ExceptT MethodError (ReaderT Context IO) [ObjectPath]
    forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
    ExceptT TaffyIO (Either MethodError [ObjectPath])
    getBatteryPaths ExceptT MethodError (ReaderT Context IO) [ObjectPath]
    -> ([ObjectPath]
        -> ExceptT
             MethodError (ReaderT Context IO) [Either MethodError ()])
    -> ExceptT MethodError (ReaderT Context IO) [Either MethodError ()]
    forall a b.
    ExceptT MethodError (ReaderT Context IO) a
    -> (a -> ExceptT MethodError (ReaderT Context IO) b)
    -> ExceptT MethodError (ReaderT Context IO) b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= IO [Either MethodError ()]
    -> ExceptT MethodError (ReaderT Context IO) [Either MethodError ()]
    forall a. IO a -> ExceptT MethodError (ReaderT Context IO) a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO [Either MethodError ()]
     -> ExceptT
          MethodError (ReaderT Context IO) [Either MethodError ()])
    -> ([ObjectPath] -> IO [Either MethodError ()])
    -> [ObjectPath]
    -> ExceptT MethodError (ReaderT Context IO) [Either MethodError ()]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ObjectPath -> IO (Either MethodError ()))
    -> [ObjectPath] -> IO [Either MethodError ()]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM ObjectPath -> IO (Either MethodError ())
    doRefresh
      let logRefreshError :: MethodError -> TaffyIO ()
    logRefreshError = Priority -> String -> MethodError -> TaffyIO ()
    forall (m :: * -> *) t.
    (MonadIO m, Show t) =>
    Priority -> String -> t -> m ()
    batteryLogF Priority
    ERROR String
    "Failed to refresh battery: %s"
          logGetPathsError :: MethodError -> TaffyIO ()
    logGetPathsError = Priority -> String -> MethodError -> TaffyIO ()
    forall (m :: * -> *) t.
    (MonadIO m, Show t) =>
    Priority -> String -> t -> m ()
    batteryLogF Priority
    ERROR String
    "Failed to get battery paths %s"

      TaffyIO () -> TaffyIO ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (TaffyIO () -> TaffyIO ()) -> TaffyIO () -> TaffyIO ()
    forall a b. (a -> b) -> a -> b
    $ (MethodError -> TaffyIO ())
    -> ([Either MethodError ()] -> TaffyIO ())
    -> Either MethodError [Either MethodError ()]
    -> TaffyIO ()
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either MethodError -> TaffyIO ()
    logGetPathsError ((Either MethodError () -> TaffyIO ())
    -> [Either MethodError ()] -> TaffyIO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ ((Either MethodError () -> TaffyIO ())
     -> [Either MethodError ()] -> TaffyIO ())
    -> (Either MethodError () -> TaffyIO ())
    -> [Either MethodError ()]
    -> TaffyIO ()
    forall a b. (a -> b) -> a -> b
    $ (MethodError -> TaffyIO ())
    -> (() -> TaffyIO ()) -> Either MethodError () -> TaffyIO ()
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either MethodError -> TaffyIO ()
    logRefreshError () -> TaffyIO ()
    forall a. a -> ReaderT Context IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return) Either MethodError [Either MethodError ()]
    eerror