Search code examples
haskellnotificationsdbusfreedesktop.org

How do I crate a value of type a{sv} for a call to org.freedesktop.Notifications.Notify via DBus?


I'm experimenting with DBus in an attempt to understand the Desktop Notifications Specification.

At the latter link I read that the method Notify has this signature

UINT32 org.freedesktop.Notifications.Notify ( app_name,    
                                              replaces_id,     
                                              app_icon,    
                                              summary,     
                                              body,    
                                              actions,     
                                              hints,   
                                              expire_timeout); 
STRING app_name;
UINT32 replaces_id;
STRING app_icon;
STRING summary;
STRING body;
as actions;
a{sv} hints;
INT32 expire_timeout;

where the argument hints has type a{sv}, and is commented as follows:

Optional hints that can be passed to the server from the client program. Although clients and servers should never assume each other supports any specific hints, they can be used to pass along information, such as the process PID or window ID, that the server may be able to make use of. See Hints. Can be empty.

So I tried to write a little haskell program that makes a call providing some dummy arguments, thinking that "Optional hints" would mean Maybe,

{-# LANGUAGE OverloadedStrings #-}

import Data.Int
import Data.Word
import Data.List (sort)
import DBus
import DBus.Client
import DBus.Internal.Types
import GHC.Generics

main = do
    client <- connectSession

    call_ client (methodCall "/org/freedesktop/Notifications" "org.freedesktop.Notifications" "Notify")
        { methodCallDestination = Just "org.freedesktop.Notifications"
        , methodCallBody = [ toVariant ("" :: String)
                           , toVariant (1 :: Word32)
                           , toVariant ("" :: String)
                           , toVariant ("" :: String)
                           , toVariant ("" :: String)
                           , toVariant ([""] :: [String])
                           , toVariant (Nothing :: Maybe [(String, Variant)]) -- compilation error
                           , toVariant (2000 :: Int32) ]
        }

but the above fails to compile because there is No instance for (IsVariant (Maybe [(String, Variant)])).

An earlier attempt was to do

                           , toVariant ([] :: [(String, Variant)]) -- compilation error

but while this compiles, it errors with

mynot: ClientError {clientErrorMessage = "Call failed: Type of message, \8220(susssasa(sv)i)\8221, does not match expected type \8220(susssasa{sv}i)\8221", clientErrorFatal = False}

where the type [(String, Variant)] seems to map to a(sv), but I'd need a a{sv}.


Solution

  • a{sv} is a dictionary type in D-Bus. On the Haskell side, the dictionaries correspond to Map, which has a IsVariant instance. That being so, with an...

    import qualified Data.Map.Strict as Map
    

    ... you can supply an empty map for the hints:

    -- etc.
        , toVariant (Map.empty :: Map.Map String Variant)