I need to list, filter and open block devices with UDisks2. I am trying to list all the removable devices.
The GetBlockDevices
method provided by UDisks2 requires a a{sv}
type. If I am not mistaken, it's a HashTable of string keys and Variant values.
How can I use this information to list the devices? So far I tried the following:
import std.stdio, ddbus;
void main()
{
Connection conn = connectToBus();
PathIface obj = new PathIface(conn, "org.freedesktop.UDsks2",
"/org/freedesktop/UDisks2/Manager", "org.freedesktop.UDisks2.Manager");
writeln(obj.call!string("GetBlockDevices", "org.freedesktop.DBus", ???));
}
The call
method requires an Arg
at as it's last parameter. How can I provide a a{sv}
in there?
I am using the ddbus
library.
For args, I used Variant!string[string]
since Variant itself is a templated type. I also removed the superfluous "org.freedesktop.DBus" from the call method parameter.
import std.stdio, ddbus;
import ddbus: Variant;
void main()
{
Connection conn = connectToBus();
PathIface obj = new PathIface(conn, "org.freedesktop.DBus",
"/org/freedesktop/UDisks2/Manager", "org.freedesktop.UDisks2.Manager");
Variant!string[string] arg;
writeln(obj.call!string("GetBlockDevices", arg));
}
However I am getting the following error:
ddbus.exception.DBusException@../../.dub/packages/ddbus-2.3.0/ddbus/source/ddbus/thin.d(833): org.freedesktop.DBus does not understand message GetBlockDevices
Your issues are:
connectToBus()
call needs to be changed.ao
(array of object paths), but you are calling it with call!string
which means you would get back a string. Change this to call!(ObjectPath[])
Variant!string[string]
. The Variant!T
type in ddbus is a helper which will just make any type T act like a variant in the dbus protocol, but it doesn't actually allow any additional types. If you want to support passing any types ddbus supports either using std.variant : Variant
or there is a special type you can use with the ddbus variant using Variant!DBusAny
which is a more lightweight tagged union with only support for all the dbus types (and more introspection)I believe this code is what you want with all the issues fixed:
import std.stdio, ddbus;
import ddbus : Variant;
import ddbus.c_lib;
void main()
{
Connection conn = connectToBus(DBusBusType.DBUS_BUS_SYSTEM);
PathIface obj = new PathIface(conn,
busName("org.freedesktop.UDisks2"),
ObjectPath("/org/freedesktop/UDisks2/Manager"),
interfaceName("org.freedesktop.UDisks2.Manager"));
Variant!DBusAny[string] arg;
writeln(obj.call!(ObjectPath[])("GetBlockDevices", arg));
}
In this code I have also used the type-safe ddbus API, which makes the arguments in PathIface more clear. The type-safe API requires ddbus 3.0.0-beta.1 or above.
Example output:
[/org/freedesktop/UDisks2/block_devices/sdc1, /org/freedesktop/UDisks2/block_devices/sdb1, /org/freedesktop/UDisks2/block_devices/sda, /org/freedesktop/UDisks2/block_devices/nvme0n1p2, /org/freedesktop/UDisks2/block_devices/sdb3, /org/freedesktop/UDisks2/block_devices/sdc, /org/freedesktop/UDisks2/block_devices/nvme0n1, /org/freedesktop/UDisks2/block_devices/sr0, /org/freedesktop/UDisks2/block_devices/nvme0n1p1, /org/freedesktop/UDisks2/block_devices/sde, /org/freedesktop/UDisks2/block_devices/sdb2, /org/freedesktop/UDisks2/block_devices/sdb, /org/freedesktop/UDisks2/block_devices/sda1, /org/freedesktop/UDisks2/block_devices/sde1, /org/freedesktop/UDisks2/block_devices/sdb4, /org/freedesktop/UDisks2/block_devices/sdd]