arielnmz
arielnmz

Reputation: 9145

How to read property from D-Bus using LGI?

I'm trying to use lgi to subscribe to a signal and then read a property as follows:

local lgi = require("lgi")
local Gio, GLib = lgi.Gio, lgi.GLib

local name = "org.freedesktop.DBus"
local path = "/org/freedesktop/DBus"
local iface = "org.freedesktop.DBus"
Gio.DBusProxy.new_for_bus(
        Gio.BusType.SESSION,
        Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES,
        nil,
        name,
        path,
        iface,
        nil,
        function(bus_proxy)
            local conn = bus_proxy:get_connection()

            local sub_id = conn:signal_subscribe(
                    nil,
                    "org.freedesktop.DBus.Properties",
                    "PropertiesChanged",
                    "/org/mpris/MediaPlayer2",
                    nil,
                    Gio.DBusSignalFlags.NONE,
                    function()
                        local value = GLib.Variant.new(
                                "(ss)",
                                { "org.mpris.MediaPlayer2.Player",
                                  "PlaybackStatus" }
                        )
                        local playback_status = bus_proxy:call_sync(
                                "org.freedesktop.DBus.Properties.Get",
                                value,
                                Gio.DBusCallFlags.NONE,
                                -1,
                                nil
                        )
                        print(playback_status)
                    end)
        end,
        nil
)

I can see that the signal is correctly subscribed and that the callback gets called everytime I pause/unpause a video on Youtube, but the bus_proxy:call_sync gets stuck and never returns with the value of PlaybackStatus. What am I doing wrong?

Upvotes: 1

Views: 353

Answers (1)

arielnmz
arielnmz

Reputation: 9145

I didn't feel like deleting the question as the solution was quite tricky but trivial in some sense. The reason the code in the OP doesn't work is because you can't read properties from the org.mpris.MediaPlayer2.Player interface because the bus is connected to the name org.freedesktop.DBus.Properties. In this case what's needed is a new proxy for the bus that sent the signal in the first place. That would be the name shown by the sender attribute of the signal, e.g.:

dbus-monitor "path='/org/mpris/MediaPlayer2',interface='org.freedesktop.DBus.Properties'"

signal time=1662414909.222359 sender=:1.12629 -> destination=(null destination) serial=4630 path=/org/mpris/MediaPlayer2; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged string "org.mpris.MediaPlayer2.Player" array [ dict entry( string "CanGoPrevious" variant boolean true ) ] array [ ]

Gio.DBusProxy.new_for_bus(
        Gio.BusType.SESSION,
        Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES,
        nil,
        name, -- use ":1.12629" here
        path,
        iface,
        nil,
        function(bus_proxy) ... end,
)

The other thing is that I didn't know how to get the value from the returned GLib.Variant object (I assumed it was just a wrapper around a native type, like in the python bindings), but turns out I need to access the .value attribute:

https://github.com/lgi-devs/lgi/blob/master/docs/variant.md#data-access

playback_status.value

Upvotes: 1

Related Questions