dbus-client 0.2 → 0.3
raw patch · 5 files changed
+230/−98 lines, 5 filesdep ~dbus-corePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: dbus-core
API changes (from Hackage documentation)
- DBus.Client: callBlocking' :: Client -> MethodCall -> IO MethodReturn
- DBus.Client: callProxyBlocking' :: Client -> Proxy -> MemberName -> [Flag] -> [Variant] -> IO MethodReturn
+ DBus.Client: callBlocking_ :: Client -> MethodCall -> IO MethodReturn
+ DBus.Client: callProxyBlocking_ :: Client -> Proxy -> MemberName -> [Flag] -> [Variant] -> IO MethodReturn
Files
- Examples/simple.hs +43/−0
- Makefile +4/−4
- dbus-client.cabal +7/−5
- dbus-client.nw +89/−55
- hs/DBus/Client.hs +87/−34
+ Examples/simple.hs view
@@ -0,0 +1,43 @@+-- Copyright (C) 2009 John Millikin <jmillikin@gmail.com>+-- +-- This program is free software: you can redistribute it and/or modify+-- it under the terms of the GNU General Public License as published by+-- the Free Software Foundation, either version 3 of the License, or+-- any later version.+-- +-- This program is distributed in the hope that it will be useful,+-- but WITHOUT ANY WARRANTY; without even the implied warranty of+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+-- GNU General Public License for more details.+-- +-- You should have received a copy of the GNU General Public License+-- along with this program. If not, see <http://www.gnu.org/licenses/>.++{-# LANGUAGE OverloadedStrings #-}+module Main (main) where++import DBus.Bus+import DBus.Client+import DBus.Message+import DBus.Types+import Data.List (sort)++dbus :: Proxy+dbus = Proxy (RemoteObject "org.freedesktop.DBus" "/org/freedesktop/DBus") "org.freedesktop.DBus"++main :: IO ()+main = do+ -- Connect to the bus, and print which name was assigned to this+ -- connection.+ client <- mkClient =<< getSessionBus+ putStrLn $ "Connected as: " ++ show (clientName client)+ + -- Request a list of connected clients from the bus+ reply <- callProxyBlocking_ client dbus "ListNames" [] []+ + -- Pull out the body, and convert it to [String]+ let Just names = fromArray =<< fromVariant (messageBody reply !! 0)+ + -- Print each name on a line, sorted so reserved names are below+ -- temporary names.+ mapM_ putStrLn $ sort names
Makefile view
@@ -11,8 +11,8 @@ hs/DBus: mkdir -p hs/DBus -%.pdf: %.tex- xelatex "$<"- xelatex "$<"+dbus-client.pdf: dbus-client.tex+ xelatex dbus-client.tex+ xelatex dbus-client.tex -pdfs: dbus-client.pdf #manual.pdf+pdf: dbus-client.pdf
dbus-client.cabal view
@@ -1,8 +1,7 @@ name: dbus-client-version: 0.2+version: 0.3 synopsis: D-Bus client libraries-description: Connect and interact with the D-Bus IPC system.-license: GPL+license: GPL-3 license-file: License.txt author: John Millikin maintainer: jmillikin@gmail.com@@ -11,14 +10,17 @@ category: Network, Desktop stability: experimental bug-reports: mailto:jmillikin@gmail.com+homepage: http://ianen.org/haskell/dbus/+tested-with: GHC==6.10.4 extra-source-files: dbus-client.nw+ Examples/*.hs Makefile source-repository head type: darcs- location: http://patch-tag.com/r/jmillikin/dbus-client/pullrepo+ location: http://ianen.org/haskell/dbus/client/ library ghc-options: -Wall@@ -26,7 +28,7 @@ build-depends: base >=3 && < 5- , dbus-core >= 0.6+ , dbus-core >= 0.8 , containers , text
dbus-client.nw view
@@ -89,6 +89,9 @@ <<DBus/Client.hs>>= type Callback = (M.ReceivedMessage -> IO ()) +-- | 'Client's are opaque handles to an open connection and other internal+-- state.+-- data Client = Client C.Connection T.BusName (MV.MVar (Map.Map M.Serial Callback)) (MV.MVar (Map.Map T.ObjectPath Callback))@@ -114,11 +117,19 @@ Client , clientName -@ The slightly weird signature for {\tt mkClient} is designed to work with-the computations defined in {\tt DBus.Bus} -- their results can be passed-directly to {\tt mkClient} without having to perform any unpacking.- <<DBus/Client.hs>>=+-- | Create a new 'Client' from an open connection and bus name. The weird++-- signature allows 'mkClient' to use the computations in "DBus.Bus"+-- directly, without unpacking:+-- +-- @+-- client <- mkClient =<< getSessionBus+-- @+-- +-- Only one client should be created for any given connection. Otherwise,+-- they will compete to receive messages.+-- mkClient :: (C.Connection, T.BusName) -> IO Client mkClient (c, name) = do replies <- MV.newMVar Map.empty@@ -139,19 +150,19 @@ complexity to handle them. <<DBus/Client.hs>>=-send :: M.Message a => Client -> (M.Serial -> IO b) -> a -> IO b-send c f msg = do+send_ :: M.Message a => Client -> (M.Serial -> IO b) -> a -> IO b+send_ c f msg = do result <- C.send (clientConnection c) f msg case result of Left x -> error $ show x Right x -> return x -@ And since most uses of {\tt send} don't care about the message's+@ And since most uses of {\tt send\_} don't care about the message's serial, it can be reduced further. <<DBus/Client.hs>>=-sendOnly :: M.Message a => Client -> a -> IO ()-sendOnly c = send c (const $ return ())+sendOnly_ :: M.Message a => Client -> a -> IO ()+sendOnly_ c = send_ c (const $ return ()) @ Additional helper computations are useful for sending method calls, to keep track of which pending calls are currently expecting replies. The@@ -166,11 +177,15 @@ callback will be added but never removed. This could cause a space leak. <<DBus/Client.hs>>=+-- | Perform an asynchronous method call. One of the provided computations+-- will be performed depending on what message type the destination sends+-- back.+-- call :: Client -> M.MethodCall -> (M.Error -> IO ()) -> (M.MethodReturn -> IO ()) -> IO ()-call client msg onError onReturn = send client addCallback msg where+call client msg onError onReturn = send_ client addCallback msg where Client _ _ mvar _ _ = client addCallback s = MV.modifyMVar_ mvar $ return . Map.insert s callback @@ -178,10 +193,10 @@ callback (M.ReceivedMethodReturn _ _ msg') = onReturn msg' callback _ = return () -@ {\tt callBlocking} is similar, except that it waits for the reply and-returns in the current {\tt IO} thread.- <<DBus/Client.hs>>=+-- | Similar to 'call', except that it waits for the reply and returns it+-- in the current 'IO' thread.+-- callBlocking :: Client -> M.MethodCall -> IO (Either M.Error M.MethodReturn) callBlocking client msg = do mvar <- MV.newEmptyMVar@@ -190,13 +205,12 @@ (MV.putMVar mvar . Right) MV.takeMVar mvar -@ Finally, for reasons similar to {\tt send}, it's useful to have a-computation which calls a method and raises an exception if it returns-an error.- <<DBus/Client.hs>>=-callBlocking' :: Client -> M.MethodCall -> IO M.MethodReturn-callBlocking' client msg = do+-- | Similar to 'callBlocking', except that an exception is raised if the+-- destination sends back an error.+-- +callBlocking_ :: Client -> M.MethodCall -> IO M.MethodReturn+callBlocking_ client msg = do reply <- callBlocking client msg case reply of Left x -> error . TL.unpack . M.errorMessage $ x@@ -206,7 +220,7 @@ -- ** Sending messages , call , callBlocking-, callBlocking'+, callBlocking_ @ \subsubsection{Emitting signals} @@ -215,7 +229,7 @@ <<DBus/Client.hs>>= emitSignal :: Client -> M.Signal -> IO ()-emitSignal = sendOnly+emitSignal = sendOnly_ <<exports>>= -- *** Emitting signals@@ -266,7 +280,7 @@ <<DBus/Client.hs>>= unknownMethod :: Client -> M.ReceivedMessage -> IO ()-unknownMethod client msg = sendOnly client errorMsg where+unknownMethod client msg = sendOnly_ client errorMsg where M.ReceivedMethodCall serial sender _ = msg errorMsg = M.Error Const.errorUnknownMethod@@ -313,31 +327,31 @@ @ \section{Name reservation} -@ A client can request a ``well-known'' name from the bus. This allows-messages sent to that name to be received by the client, without senders-being aware of which application is actually handling requests.--A name may be requested for any client, using the given flags. The bus's-reply will be returned, or an exception raised if the reply was invalid.- <<imports>>= import qualified DBus.NameReservation as NR <<DBus/Client.hs>>=+-- | A client can request a \"well-known\" name from the bus. This allows+-- messages sent to that name to be received by the client, without senders+-- being aware of which application is actually handling requests.+-- +-- A name may be requested for any client, using the given flags. The bus's+-- reply will be returned, or an exception raised if the reply was invalid.+-- requestName :: Client -> T.BusName -> [NR.RequestNameFlag] -> IO NR.RequestNameReply requestName client name flags = do- reply <- callBlocking' client $ NR.requestName name flags+ reply <- callBlocking_ client $ NR.requestName name flags case NR.mkRequestNameReply reply of Nothing -> error $ "Invalid reply to RequestName" Just x -> return x -@ Releasing a name is similar, except there's no flags.- <<DBus/Client.hs>>=+-- | Clients may also release names they've requested.+-- releaseName :: Client -> T.BusName -> IO NR.ReleaseNameReply releaseName client name = do- reply <- callBlocking' client $ NR.releaseName name+ reply <- callBlocking_ client $ NR.releaseName name case NR.mkReleaseNameReply reply of Nothing -> error $ "Invalid reply to ReleaseName" Just x -> return x@@ -358,6 +372,9 @@ import Data.Maybe (fromJust) <<DBus/Client.hs>>=+-- | Perform some computation every time this client receives a matching+-- signal.+-- onSignal :: Client -> MR.MatchRule -> (T.BusName -> M.Signal -> IO ()) -> IO ()@@ -370,7 +387,7 @@ callback' _ = return () in do- callBlocking' client $ MR.addMatch rule'+ callBlocking_ client $ MR.addMatch rule' MV.modifyMVar_ mvar $ return . (callback' :) <<exports>>=@@ -402,6 +419,9 @@ (Set.fromList flags) body <<DBus/Client.hs>>=+-- | As 'call', except that the proxy's information is used to+-- build the message.+-- callProxy :: Client -> Proxy -> T.MemberName -> [M.Flag] -> [T.Variant] -> (M.Error -> IO ()) -> (M.MethodReturn -> IO ())@@ -411,6 +431,9 @@ in call client msg onError onReturn <<DBus/Client.hs>>=+-- | As 'callBlocking', except that the proxy's information is used+-- to build the message.+-- callProxyBlocking :: Client -> Proxy -> T.MemberName -> [M.Flag] -> [T.Variant] -> IO (Either M.Error M.MethodReturn)@@ -418,16 +441,19 @@ callBlocking client $ buildMethodCall proxy name flags body <<DBus/Client.hs>>=-callProxyBlocking' :: Client -> Proxy -> T.MemberName -> [M.Flag]+-- | As 'callBlocking_', except that the proxy's information is used+-- to build the message.+-- +callProxyBlocking_ :: Client -> Proxy -> T.MemberName -> [M.Flag] -> [T.Variant] -> IO M.MethodReturn-callProxyBlocking' client proxy name flags body =- callBlocking' client $ buildMethodCall proxy name flags body+callProxyBlocking_ client proxy name flags body =+ callBlocking_ client $ buildMethodCall proxy name flags body <<exports>>= , callProxy , callProxyBlocking-, callProxyBlocking'+, callProxyBlocking_ @ \subsection{Signals} @@ -459,27 +485,24 @@ import qualified DBus.Introspection as I <<initialize client>>=-export client (T.mkObjectPath' "/") rootObject+export client ("/") rootObject <<DBus/Client.hs>>= rootObject :: LocalObject rootObject = LocalObject $ Map.fromList [(ifaceName, interface)] where- ifaceName = T.mkInterfaceName' "org.freedesktop.DBus.Introspectable"- memberName = T.mkMemberName' "Introspect"- inSig = T.mkSignature' ""- outSig = T.mkSignature' "s"+ ifaceName = "org.freedesktop.DBus.Introspectable"+ memberName = "Introspect" interface = Interface $ Map.fromList [(memberName, impl)] - method = I.Method memberName [] [I.Parameter "xml" outSig]+ method = I.Method memberName [] [I.Parameter "xml" "s"] iface = I.Interface ifaceName [method] [] []- path = T.mkObjectPath' "/" - impl = Method inSig outSig $ \call' -> do+ impl = Method "" "s" $ \call' -> do let Client _ _ _ mvar _ = methodCallClient call' paths <- fmap Map.keys $ MV.readMVar mvar - let paths' = filter (/= path) paths- let Just xml = I.toXML $ I.Object path [iface]+ let paths' = filter (/= "/") paths+ let Just xml = I.toXML $ I.Object "/" [iface] [I.Object p [] [] | p <- paths'] replyReturn call' [T.toVariant xml] @@ -501,6 +524,13 @@ | Signal T.Signature <<DBus/Client.hs>>=+-- | Export a set of interfaces on the bus. Whenever a method call is+-- received which matches the object's path, interface, and member name,+-- one of its members will be called.+-- +-- Exported objects automatically implement the+-- @org.freedesktop.DBus.Introspectable@ interface.+-- export :: Client -> T.ObjectPath -> LocalObject -> IO () export client@(Client _ _ _ mvar _) path obj = MV.modifyMVar_ mvar $ return . Map.insert path (onMethodCall client (addIntrospectable path obj))@@ -509,9 +539,9 @@ addIntrospectable :: T.ObjectPath -> LocalObject -> LocalObject addIntrospectable path (LocalObject ifaces) = LocalObject ifaces' where ifaces' = Map.insertWith (\_ x -> x) name iface ifaces- name = T.mkInterfaceName' "org.freedesktop.DBus.Introspectable"- iface = Interface $ Map.fromList [(T.mkMemberName' "Introspect", impl)]- impl = Method (T.mkSignature' "") (T.mkSignature' "s") $ \call' -> do+ name = "org.freedesktop.DBus.Introspectable"+ iface = Interface $ Map.fromList [("Introspect", impl)]+ impl = Method "" "s" $ \call' -> do let Just xml = I.toXML . introspect path . methodCallObject $ call' replyReturn call' [T.toVariant xml] @@ -539,7 +569,7 @@ (map introspectParam (T.signatureTypes sig))] introspectSignal _ = [] - introspectParam = I.Parameter "" . T.mkSignature' . T.typeCode+ introspectParam = I.Parameter "" . T.mkSignature_ . T.typeCode @ \subsection{Responding to method calls} @@ -571,7 +601,7 @@ let M.ReceivedMethodCall serial sender call' = msg sigStr = TL.concat . map (T.typeCode . T.variantType) . M.methodCallBody $ call'- sig = T.mkSignature' sigStr+ sig = T.mkSignature_ sigStr case findMember call' obj of Just method@(Method inSig _ x) -> let@@ -587,6 +617,8 @@ <<DBus/Client.hs>>=+-- | Send a successful return reply for a method call.+-- replyReturn :: MethodCall -> [T.Variant] -> IO () replyReturn call' body = reply where replyInvalid = M.Error@@ -601,7 +633,7 @@ body sendReply :: M.Message a => a -> IO ()- sendReply = sendOnly (methodCallClient call')+ sendReply = sendOnly_ (methodCallClient call') sigStr = TL.concat . map (T.typeCode . T.variantType) $ body (Method _ outSig _) = methodCallMethod call'@@ -610,8 +642,10 @@ else sendReply replyInvalid <<DBus/Client.hs>>=+-- | Send an error reply for a method call.+-- replyError :: MethodCall -> T.ErrorName -> [T.Variant] -> IO ()-replyError call' name body = sendOnly c reply where+replyError call' name body = sendOnly_ c reply where c = methodCallClient call' reply = M.Error name
hs/DBus/Client.hs view
@@ -26,7 +26,7 @@ -- ** Sending messages , call , callBlocking- , callBlocking'+ , callBlocking_ -- *** Emitting signals , emitSignal@@ -44,7 +44,7 @@ , callProxy , callProxyBlocking- , callProxyBlocking'+ , callProxyBlocking_ , onSignalFrom @@ -85,6 +85,8 @@ type Callback = (M.ReceivedMessage -> IO ()) +-- | 'Client's are opaque handles to an open connection and other internal+-- state. data Client = Client C.Connection T.BusName (MV.MVar (Map.Map M.Serial Callback)) (MV.MVar (Map.Map T.ObjectPath Callback))@@ -96,6 +98,18 @@ clientName :: Client -> T.BusName clientName (Client _ x _ _ _) = x +-- | Create a new 'Client' from an open connection and bus name. The weird++-- signature allows 'mkClient' to use the computations in "DBus.Bus"+-- directly, without unpacking:+-- +-- @+-- client <- mkClient =<< getSessionBus+-- @+-- +-- Only one client should be created for any given connection. Otherwise,+-- they will compete to receive messages.+-- mkClient :: (C.Connection, T.BusName) -> IO Client mkClient (c, name) = do replies <- MV.newMVar Map.empty@@ -104,25 +118,29 @@ let client = Client c name replies exports signals forkIO $ forever (receiveMessages client) - export client (T.mkObjectPath' "/") rootObject+ export client ("/") rootObject return client -send :: M.Message a => Client -> (M.Serial -> IO b) -> a -> IO b-send c f msg = do+send_ :: M.Message a => Client -> (M.Serial -> IO b) -> a -> IO b+send_ c f msg = do result <- C.send (clientConnection c) f msg case result of Left x -> error $ show x Right x -> return x -sendOnly :: M.Message a => Client -> a -> IO ()-sendOnly c = send c (const $ return ())+sendOnly_ :: M.Message a => Client -> a -> IO ()+sendOnly_ c = send_ c (const $ return ()) +-- | Perform an asynchronous method call. One of the provided computations+-- will be performed depending on what message type the destination sends+-- back.+-- call :: Client -> M.MethodCall -> (M.Error -> IO ()) -> (M.MethodReturn -> IO ()) -> IO ()-call client msg onError onReturn = send client addCallback msg where+call client msg onError onReturn = send_ client addCallback msg where Client _ _ mvar _ _ = client addCallback s = MV.modifyMVar_ mvar $ return . Map.insert s callback @@ -130,6 +148,9 @@ callback (M.ReceivedMethodReturn _ _ msg') = onReturn msg' callback _ = return () +-- | Similar to 'call', except that it waits for the reply and returns it+-- in the current 'IO' thread.+-- callBlocking :: Client -> M.MethodCall -> IO (Either M.Error M.MethodReturn) callBlocking client msg = do mvar <- MV.newEmptyMVar@@ -138,15 +159,18 @@ (MV.putMVar mvar . Right) MV.takeMVar mvar -callBlocking' :: Client -> M.MethodCall -> IO M.MethodReturn-callBlocking' client msg = do+-- | Similar to 'callBlocking', except that an exception is raised if the+-- destination sends back an error.+-- +callBlocking_ :: Client -> M.MethodCall -> IO M.MethodReturn+callBlocking_ client msg = do reply <- callBlocking client msg case reply of Left x -> error . TL.unpack . M.errorMessage $ x Right x -> return x emitSignal :: Client -> M.Signal -> IO ()-emitSignal = sendOnly+emitSignal = sendOnly_ receiveMessages :: Client -> IO () receiveMessages client = do@@ -175,7 +199,7 @@ handleMessage _ _ = return () unknownMethod :: Client -> M.ReceivedMessage -> IO ()-unknownMethod client msg = sendOnly client errorMsg where+unknownMethod client msg = sendOnly_ client errorMsg where M.ReceivedMethodCall serial sender _ = msg errorMsg = M.Error Const.errorUnknownMethod@@ -194,21 +218,33 @@ Just x -> forkIO (x msg) >> return () Nothing -> return () +-- | A client can request a \"well-known\" name from the bus. This allows+-- messages sent to that name to be received by the client, without senders+-- being aware of which application is actually handling requests.+-- +-- A name may be requested for any client, using the given flags. The bus's+-- reply will be returned, or an exception raised if the reply was invalid.+-- requestName :: Client -> T.BusName -> [NR.RequestNameFlag] -> IO NR.RequestNameReply requestName client name flags = do- reply <- callBlocking' client $ NR.requestName name flags+ reply <- callBlocking_ client $ NR.requestName name flags case NR.mkRequestNameReply reply of Nothing -> error $ "Invalid reply to RequestName" Just x -> return x +-- | Clients may also release names they've requested.+-- releaseName :: Client -> T.BusName -> IO NR.ReleaseNameReply releaseName client name = do- reply <- callBlocking' client $ NR.releaseName name+ reply <- callBlocking_ client $ NR.releaseName name case NR.mkReleaseNameReply reply of Nothing -> error $ "Invalid reply to ReleaseName" Just x -> return x +-- | Perform some computation every time this client receives a matching+-- signal.+-- onSignal :: Client -> MR.MatchRule -> (T.BusName -> M.Signal -> IO ()) -> IO ()@@ -221,7 +257,7 @@ callback' _ = return () in do- callBlocking' client $ MR.addMatch rule'+ callBlocking_ client $ MR.addMatch rule' MV.modifyMVar_ mvar $ return . (callback' :) data RemoteObject = RemoteObject T.BusName T.ObjectPath@@ -234,6 +270,9 @@ msg = M.MethodCall path name (Just iface) (Just dest) (Set.fromList flags) body +-- | As 'call', except that the proxy's information is used to+-- build the message.+-- callProxy :: Client -> Proxy -> T.MemberName -> [M.Flag] -> [T.Variant] -> (M.Error -> IO ()) -> (M.MethodReturn -> IO ())@@ -242,17 +281,23 @@ msg = buildMethodCall proxy name flags body in call client msg onError onReturn +-- | As 'callBlocking', except that the proxy's information is used+-- to build the message.+-- callProxyBlocking :: Client -> Proxy -> T.MemberName -> [M.Flag] -> [T.Variant] -> IO (Either M.Error M.MethodReturn) callProxyBlocking client proxy name flags body = callBlocking client $ buildMethodCall proxy name flags body -callProxyBlocking' :: Client -> Proxy -> T.MemberName -> [M.Flag]+-- | As 'callBlocking_', except that the proxy's information is used+-- to build the message.+-- +callProxyBlocking_ :: Client -> Proxy -> T.MemberName -> [M.Flag] -> [T.Variant] -> IO M.MethodReturn-callProxyBlocking' client proxy name flags body =- callBlocking' client $ buildMethodCall proxy name flags body+callProxyBlocking_ client proxy name flags body =+ callBlocking_ client $ buildMethodCall proxy name flags body onSignalFrom :: Client -> Proxy -> T.MemberName -> (M.Signal -> IO ()) -> IO ()@@ -271,22 +316,19 @@ rootObject :: LocalObject rootObject = LocalObject $ Map.fromList [(ifaceName, interface)] where- ifaceName = T.mkInterfaceName' "org.freedesktop.DBus.Introspectable"- memberName = T.mkMemberName' "Introspect"- inSig = T.mkSignature' ""- outSig = T.mkSignature' "s"+ ifaceName = "org.freedesktop.DBus.Introspectable"+ memberName = "Introspect" interface = Interface $ Map.fromList [(memberName, impl)] - method = I.Method memberName [] [I.Parameter "xml" outSig]+ method = I.Method memberName [] [I.Parameter "xml" "s"] iface = I.Interface ifaceName [method] [] []- path = T.mkObjectPath' "/" - impl = Method inSig outSig $ \call' -> do+ impl = Method "" "s" $ \call' -> do let Client _ _ _ mvar _ = methodCallClient call' paths <- fmap Map.keys $ MV.readMVar mvar - let paths' = filter (/= path) paths- let Just xml = I.toXML $ I.Object path [iface]+ let paths' = filter (/= "/") paths+ let Just xml = I.toXML $ I.Object "/" [iface] [I.Object p [] [] | p <- paths'] replyReturn call' [T.toVariant xml] @@ -296,6 +338,13 @@ = Method T.Signature T.Signature (MethodCall -> IO ()) | Signal T.Signature +-- | Export a set of interfaces on the bus. Whenever a method call is+-- received which matches the object's path, interface, and member name,+-- one of its members will be called.+-- +-- Exported objects automatically implement the+-- @org.freedesktop.DBus.Introspectable@ interface.+-- export :: Client -> T.ObjectPath -> LocalObject -> IO () export client@(Client _ _ _ mvar _) path obj = MV.modifyMVar_ mvar $ return . Map.insert path (onMethodCall client (addIntrospectable path obj))@@ -303,9 +352,9 @@ addIntrospectable :: T.ObjectPath -> LocalObject -> LocalObject addIntrospectable path (LocalObject ifaces) = LocalObject ifaces' where ifaces' = Map.insertWith (\_ x -> x) name iface ifaces- name = T.mkInterfaceName' "org.freedesktop.DBus.Introspectable"- iface = Interface $ Map.fromList [(T.mkMemberName' "Introspect", impl)]- impl = Method (T.mkSignature' "") (T.mkSignature' "s") $ \call' -> do+ name = "org.freedesktop.DBus.Introspectable"+ iface = Interface $ Map.fromList [("Introspect", impl)]+ impl = Method "" "s" $ \call' -> do let Just xml = I.toXML . introspect path . methodCallObject $ call' replyReturn call' [T.toVariant xml] @@ -332,7 +381,7 @@ (map introspectParam (T.signatureTypes sig))] introspectSignal _ = [] - introspectParam = I.Parameter "" . T.mkSignature' . T.typeCode+ introspectParam = I.Parameter "" . T.mkSignature_ . T.typeCode data MethodCall = MethodCall { methodCallObject :: LocalObject@@ -355,7 +404,7 @@ let M.ReceivedMethodCall serial sender call' = msg sigStr = TL.concat . map (T.typeCode . T.variantType) . M.methodCallBody $ call'- sig = T.mkSignature' sigStr+ sig = T.mkSignature_ sigStr case findMember call' obj of Just method@(Method inSig _ x) -> let@@ -370,6 +419,8 @@ _ -> unknownMethod client msg +-- | Send a successful return reply for a method call.+-- replyReturn :: MethodCall -> [T.Variant] -> IO () replyReturn call' body = reply where replyInvalid = M.Error@@ -384,7 +435,7 @@ body sendReply :: M.Message a => a -> IO ()- sendReply = sendOnly (methodCallClient call')+ sendReply = sendOnly_ (methodCallClient call') sigStr = TL.concat . map (T.typeCode . T.variantType) $ body (Method _ outSig _) = methodCallMethod call'@@ -392,8 +443,10 @@ then sendReply replyValid else sendReply replyInvalid +-- | Send an error reply for a method call.+-- replyError :: MethodCall -> T.ErrorName -> [T.Variant] -> IO ()-replyError call' name body = sendOnly c reply where+replyError call' name body = sendOnly_ c reply where c = methodCallClient call' reply = M.Error name