oprypin / crystal-dbus

Crystal bindings to D-Bus
MIT License
12 stars 6 forks source link

Documentation / Guide #8

Closed BigBoyBarney closed 2 weeks ago

BigBoyBarney commented 3 weeks ago

Hi!

First of all, thanks for this shard. Exactly what I was looking for.

With the help of the example and some trial and error, I got simple calls working, and can retrieve metadata from mpv for example, with:

require "dbus"

bus = DBus::Bus.new
dest = bus.destination("org.mpris.MediaPlayer2.mpv")
metadata = dest.object("/org/mpris/MediaPlayer2").interface("org.mpris.MediaPlayer2.Player").get("Metadata")
puts metadata.reply

I'm stuck at this point though, and cannot extract the title for example (and even the #reply was just a guess based on the generated docs).

Without any real documentation, guide or examples, it is almost impossible to figure out what to do.

Would it be possible to write a very short description about some of the main use-cases? Getting properties, making calls etc.

If you could provide some cursory guidance, I would gladly help write documentation :D

Thanks in advance!

oprypin commented 3 weeks ago

Hi. Oh boy, took me half an hour to figure this out. Here's how to get the title :facepalm:

puts metadata.reply[0].as(DBus::Variant).value.as(Hash)["xesam:title"].as(DBus::Variant).value.as(String)

It's not very nice...

Honestly this library is not great, now that I look at it :D

It should be possible to implement DBus::Serializable for it, that would be much better. Or at the very least DBus::Any. Like for JSON.

oprypin commented 3 weeks ago

I really didn't put much thought into the implementation of properties. Basically in 100% of cases this code snippet will be guaranteed to be at the start: .reply[0].as(DBus::Variant).value - and then you can start digging into the actual value. This is because a property is like a method that always has exactly 1 output parameter of the type "variant".

BigBoyBarney commented 2 weeks ago

Thank you, that works! Wrapping a method around it makes it less unwieldy, so it's not the end of the world. I noticed that puts metadata.reply[0] neither errors nor returns nil when the DBus path doesn't exist.

The following code is valid and returns a DBus::Type. If I try to cast this .as(DBus::Variant), it raises an error.

require "dbus"

bus = DBus::Bus.new
dest = bus.destination("Pokemon.Snorlax")
metadata = dest.object("/pokemon/snorlax").interface("pokemon.snorlax").get("something")
puts metadata.reply[0]
puts typeof(metadata.reply[0])

Would it perhaps be possible to handle cases where the destination / interface / object don't exist, and raise or return nil it gets to the cast?

Additionally, are DBus signals supported? I would gladly help with development, but I'm not entirely sure where to start. If you could point me in a direction, I could have a look too :D

Thanks in advance!! <3

oprypin commented 2 weeks ago

Hi again! I'm sorry, I don't really have much of an idea how anything works here. It's been like 7 years that i hadn't looked at this at all

oprypin commented 2 weeks ago

And signals are not supported 😔 needs a server implementation

BigBoyBarney commented 2 weeks ago

That is completely fair, thank you for looking into this regardless!

Cheers!