tianbar-0.3.3.0: src/System/Tianbar/DBus.hs
{-# Language OverloadedStrings #-}
module System.Tianbar.DBus where
import Control.Concurrent.MVar
import Control.Monad
import Data.Aeson
import Data.Int
import Data.List
import qualified Data.Map as M
import qualified Data.Text.Lazy as T
import qualified Data.Text.Lazy.Encoding as E
import Data.Word
import qualified Graphics.UI.Gtk as Gtk
import Graphics.UI.Gtk.WebKit.WebView
import DBus
import DBus.Client
import Network.URI
import System.Tianbar.UriOverride
-- DBus callback override
data DBusState = DBusState { dbusClient :: MVar Client
}
instance ToJSON Variant where
toJSON v = let t = variantType v in
case t of
TypeBoolean -> let Just b = fromVariant v :: Maybe Bool in toJSON b
TypeString -> let Just s = fromVariant v :: Maybe String in toJSON s
TypeWord8 -> let Just i = fromVariant v :: Maybe Word8 in toJSON i
TypeWord16 -> let Just i = fromVariant v :: Maybe Word16 in toJSON i
TypeWord32 -> let Just i = fromVariant v :: Maybe Word32 in toJSON i
TypeWord64 -> let Just i = fromVariant v :: Maybe Word64 in toJSON i
TypeInt16 -> let Just i = fromVariant v :: Maybe Int16 in toJSON i
TypeInt32 -> let Just i = fromVariant v :: Maybe Int32 in toJSON i
TypeInt64 -> let Just i = fromVariant v :: Maybe Int64 in toJSON i
-- TODO: more types
_ -> error $ "Variant type not supported: "
++ show v ++ " (type: " ++ show t ++ ")"
instance ToJSON Signal where
toJSON s = object [ "path" .= toJSON (formatObjectPath $ signalPath s)
, "iface" .= toJSON (formatInterfaceName $ signalInterface s)
, "member" .= toJSON (formatMemberName $ signalMember s)
]
callback :: WebView -> Int -> Signal -> IO ()
callback wk index sig =
Gtk.postGUIAsync $ webViewExecuteScript wk $ dbusCallback index sig
dbusCallback :: Int -> Signal -> String
dbusCallback index sig =
"window.dbusCallbacks && "
++ "window.dbusCallbacks[" ++ indexStr ++ "](" ++ paramsStr ++ ")"
where indexStr = show index
paramsStr = intercalate "," $ map (T.unpack . E.decodeUtf8) [signalStr, bodyStr]
signalStr = encode $ toJSON sig
bodyStr = encode $ toJSON $ signalBody sig
dbusOverride :: WebView -> DBusState -> UriOverride
dbusOverride wk dbus = withScheme "dbus:" $ \uri -> do
case uriPath uri of
"listen" -> dbusListen wk dbus uri
_ -> return ()
returnContent ""
dbusListen :: WebView -> DBusState -> URI -> IO ()
dbusListen wk dbus uri = do
let params = parseQuery uri
let matcher = matchAny { matchSender = Nothing
, matchDestination = Nothing
, matchPath = M.lookup "path" params >>= parseObjectPath
, matchInterface = M.lookup "iface" params >>= parseInterfaceName
, matchMember = M.lookup "member" params >>= parseMemberName
}
let (Just index) = liftM read $ M.lookup "index" params
withMVar (dbusClient dbus) $ \client ->
listen client matcher $ callback wk index