lgi-devs / lgi

Dynamic Lua binding to GObject libraries using GObject-Introspection
MIT License
440 stars 70 forks source link

BecomeMonitor? #200

Closed kalkbrenner closed 6 years ago

kalkbrenner commented 6 years ago

Hi,

i tried to use the dbus monitoring interface like:

    local lgi = require 'lgi'
    local Gio = lgi.require 'Gio'
    local GVariant = lgi.GLib.Variant
    local GLib = require("lgi").GLib

    local bus = Gio.bus_get_sync(Gio.BusType.SYSTEM)

    local params = GVariant("(asu)",{ {}, 0})
    local var, err = bus:call_sync('org.freedesktop.DBus',
      '/org/freedesktop/DBus',
      'org.freedesktop.DBus.Monitoring',
      'BecomeMonitor',
      params,
      nil,
      Gio.DBusCallFlags.NONE,
      -1
    )

  local ctx = GLib.MainLoop():get_context()
  while true do
    if ctx:iteration(true) == true then
      print("do something with the bus to get the signals/messages")
    end
  end

which seems to work (no errors, busctl monitor output looks correct), but I have no idea how I can get the signals/messages which should be send to the session/me now.

Can someone give me a hint?

Thanks, Björn

psychon commented 6 years ago

Uhm, well... Do you have some example of C code that you want to translate?

So far, I found the DBus specification which however does not seem all that clear to me. Or is "Monitor connections may receive all messages" actually the description that should explain everything?

When I replace SYSTEM with SESSION in your example, run the program, and run notify-send test, then the Lua process just exits with a traceback that suggests that "the other end" of the DBus connection was closed. So, this does not work.

psychon commented 6 years ago

Ah, setting G_DBUS_DEBUG=all helped.

So, apparently "BecomeMonitor" really just means that the connection gets all kinds of random messages. This can be seen in G_DBUS_DEBUG=all. The problem is that GDBus does not expect this and thus replies to messages (with error messages). Per the DBus specification I linked above, this is illegal and means that the DBus daemon closes the connection.

None of this is related to LGI.

To answer your question: I guess that g_dbus_connection_add_filter could be helpful for you. I replaced the "lower part" of your code with the following and it seems to work reasonably well:

    bus:add_filter(function(...)
        print(...)
        return nil
    end)
   GLib.MainLoop().new():run()
psychon commented 6 years ago

Well, okay, three more things:

    bus:add_filter(function(a, msg, ...)
        print(a, msg, ...)
        print(msg:print(0))
        return nil
    end)

and https://developer.gnome.org/gio/stable/GDBusMessage.html to figure out how to look at GDBusMessage instances (which is what msg is here).

Note that the above is totally unsafe. Per the API docs for add_filter:

Note that filters are run in a dedicated message handling thread so they can't block and, generally, can't do anything but signal a worker thread.

With LGI, calling the filter can block, because Lua is not thread-safe and so LGI acquires a lock here.

kalkbrenner commented 6 years ago

Awesome help, thank you very much psychon!

You also answered another question in my head - how can the gnome documentation be "mapped" to the code written with lgi (bus:add_filter => g_dbus_connection_add_filter; msg:print => g_dbus_message_print, ...) - just that "easy". Your code works perfect as starting point, I'll try to go further and get bus:signal_subscribe() not to terminate - but I think I can dig deeper on my own now.

Again, thanks for help!

timroes commented 2 years ago

Sorry for pinging on this old closed issue here. I am trying to achieve the very same thing (trying to use BecomeMonitor using LGI - from within my awesome WM configuration) and wonder if you ever got this fully (safely) to work and would mind posting/linking your code here?

(My use-case is basically observing the org.freedesktop.ScreenSaver.Inhibit calls, which light-locker is listening for, so I'd know the state on whether the screen saver is currently inhibited or not. Unfortunately light-locker has no other way of exposing that information.)