xmonad-config/lib/Xmobar/Plugins/Bluetooth.hs

67 lines
2.1 KiB
Haskell
Raw Normal View History

2020-03-21 01:18:38 -04:00
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Xmobar.Plugins.Bluetooth where
import Control.Concurrent
import Control.Monad
2020-03-21 14:30:27 -04:00
import qualified Data.Map.Lazy as M
import Data.Maybe
2020-03-21 01:18:38 -04:00
import DBus
import DBus.Client
2020-03-21 14:30:27 -04:00
import DBus.Internal.Types
2020-03-21 01:18:38 -04:00
import Xmobar
newtype Bluetooth = Bluetooth (String, String, String) deriving (Read, Show)
2020-03-21 14:30:27 -04:00
path :: ObjectPath
path = "/org/bluez/hci0"
interface :: InterfaceName
interface = "org.freedesktop.DBus.Properties"
2020-03-21 01:18:38 -04:00
rule :: MatchRule
rule = matchAny
2020-03-21 14:30:27 -04:00
{ matchPath = Just path
, matchInterface = Just interface
2020-03-21 01:18:38 -04:00
, matchMember = Just "PropertiesChanged"
}
2020-03-21 14:30:27 -04:00
callBT :: Client -> IO (Either MethodError MethodReturn)
callBT client =
call client (methodCall path interface "Get")
{ methodCallDestination = Just "org.bluez", methodCallBody = body }
where
body = map toVariant ["org.bluez.Adapter1", "Powered" :: String]
2020-03-21 01:18:38 -04:00
instance Exec Bluetooth where
alias (Bluetooth _) = "bluetooth"
start (Bluetooth (text, colorOn, colorOff)) cb = do
client <- connectSystem
2020-03-21 14:30:27 -04:00
_ <- addMatch client rule $
cb . fmtState . lookupState . getProps . signalBody
reply <- callBT client
-- TODO handle errors?
case reply of
Right ret -> cb $ fmtState $ fromVariant =<< fromVariant
2020-03-21 14:30:27 -04:00
=<< listToMaybe (methodReturnBody ret)
Left _ -> return ()
forever (threadDelay 5000000)
2020-03-21 01:18:38 -04:00
where
2020-03-21 14:30:27 -04:00
-- Assume that the data in the PropertiesChanged signal has the form
-- [something, Map, something] where the Map in the middle has the
-- "Powered" text key that we care about (among other things that change
-- when the bluetooth interface is powered on)
getProps = \case
[_, Variant (ValueMap TypeString TypeVariant m), _] -> Just m
_ -> Nothing
lookupState m = fromVariant =<< fromValue
=<< M.lookup (AtomText "Powered") =<< m
2020-03-21 01:18:38 -04:00
fmtState = \case
Just s -> wrapColor text $ if s then colorOn else colorOff
Nothing -> "N/A"
wrapColor s c = "<fc=" ++ c ++ ">" ++ s ++ "</fc>"