carbolymer
carbolymer

Reputation: 1632

How to set dbus interface property in Haskell?

I'm trying to replicate behaviour of the two dbus-send commands for controlling dunst notifications in Haskell:

getting a property:

dbus-send --print-reply=literal \
  --dest="org.freedesktop.Notifications" \
  "/org/freedesktop/Notifications" \
  "org.freedesktop.DBus.Properties.Get" \
  "string:org.dunstproject.cmd0" \
  "string:paused"

and setting a property:

dbus-send --print-reply=literal \
  --dest="org.freedesktop.Notifications" \
  "/org/freedesktop/Notifications" \
  "org.freedesktop.DBus.Properties.Set" \
  "string:org.dunstproject.cmd0" \
  "string:paused" \
  "variant:boolean:true"

Both dbus-send commands work just fine. I have the following haskell code using dbus library trying to achieve the same:

import DBus qualified as DBus
import DBus.Client qualified as DBus

getPaused = do
  let methodCall =
        (DBus.methodCall "/org/freedesktop/Notifications" "org.dunstproject.cmd0" "paused")
          { DBus.methodCallDestination = Just "org.freedesktop.Notifications"
          }
  client <- DBus.connectSession
  res <- DBus.getPropertyValue @Bool client methodCall
  print res


setPaused = do
  let methodCall =
        (DBus.methodCall "/org/freedesktop/Notifications" "org.dunstproject.cmd0" "paused")
          { DBus.methodCallDestination = Just "org.freedesktop.Notifications"
          }
  client <- DBus.connectSession
  res <- DBus.setPropertyValue client methodCall True
  print res

While getPaused works correctly and prints the current property value, setPaused prints an error:

Just (MethodError 
  { methodErrorName = ErrorName "org.freedesktop.DBus.Error.UnknownMethod"
  , methodErrorSerial = Serial 2
  , methodErrorSender = Just (BusName ":1.11")
  , methodErrorDestination = Just (BusName ":1.475")
  , methodErrorBody = 
     [Variant 
        "No such interface \8220org.freedesktop.DBus.Properties\8221 on object at path /org/freedesktop/Notifications"
     ]
  })

What is still missing here to set the property correctly?

Upvotes: 1

Views: 61

Answers (1)

K. A. Buhr
K. A. Buhr

Reputation: 51109

My apologies. I made a small mistake in my testing and am now able to reproduce the issue. The problem is that in order for the DBus.setPropertyValue call to generate the same request as the corresponding dbus-send call, you need to wrap the boolean value in a variant.

So, if you replace the line in your setPaused call with:

res <- DBus.setPropertyValue client methodCall (DBus.toVariant True)  -- 

it should work like the dbus-send version.

It's unclear if this is working as designed, or if it represents a bug in setPropertyValue (or its underlying setProperty function).

Upvotes: 2

Related Questions