Using Emacs to Monitor Dbus

Sure, sure, I make problems for myself by insisting on having things “just right”… for me. This blog post is about trying to fix those self made problems.

OK, thing the first:

See that “Turn on power saver mode when battery power is low” thing? Yes, indeed, it’s an on/off toggle: You’re not allowed to specify what “low” is. You used to be able to do that in Gnome Shell, but that was apparently not user friendly enough. (For all I know, perhaps you’re still allowed to do that somehow, but google didn’t help.)

It turns out that this is 20%, which I guess is a reasonable value… IF YOU”RE CHICKENSHIT! When the machine is in “power saver mode”, you can basically not use it normally (it dims the screen after a couple seconds of inactivity etc and nags at you), so you’re giving up one fifth of your effective battery capacity.

So for years, I’ve just switched it off, and if I forget to notice the battery indicator has counted down to 0%, well, then the machine switches itself off in the middle of me typing something.

Thing the second:

When I close the lid of the laptop, I don’t want anything to happen (except switching the screen off). In particular, I don’t want the machine to go to sleep, because I normally have several network connections up, and I don’t want those to be lost willy nilly.

That is, I close the lid routinely to move around and futz around in general, and I don’t want that to be disruptive in any way — and I certainly don’t want to be one of those people that walk around with a half-open laptop! The horrors!

(Our model is here demonstrating the proper way to hold a laptop while walking around.)

The lid action used to be handled by the desktop environment, but in their infinite wisdom, this (as most everything else) has moved to systemd:

HandleLidSwitch=ignore

And this… makes the laptop ignore me closing the lid. And ignore means ignore — it doesn’t switch the screen off, either!

I mean, it’s not a catastrophe, but…

Finally, thing the third:

Since 1997, I’ve used an Emacs-based music player. (Three decade anniversary coming up soon!) I use it at home, of course, but I also use it while travelling, and that’s the problem. Because when I’m in hotel rooms, it’s sooo annoying to have to switch whatever bluetooth speaker I’m using on, and then open the laptop, find Emacs, and press z (for unpause). And then when going out, it’s the same thing, only in reverse! This cannot stand! It’s an outrage!

So I thought… all these things have in common that they are events that I want to react to, but in my own way. What would be an easy way to detect these events?

Well, there’s Dbus.

dbus-monitor --system certainly says that there’s a lot of information passing over that bus, so perhaps that’s all I need?

So I looked at the Emacs Dbus documentation… and that sounds promising. And the documentation in my somewhat older Emacs says:

dbus-register-signal is a byte-compiled Lisp function in dbus.el.

(dbus-register-signal BUS SERVICE PATH INTERFACE SIGNAL HANDLER &rest
ARGS)

Register for a signal on the D-Bus BUS.

[...]

SERVICE, PATH, INTERFACE and SIGNAL can be nil.  This is
interpreted as a wildcard for the respective argument.

OK, and I just want (as a first step) just to see what data is available, so since all those things can be wildcards, this should work, right?

(defun my-signal-handler (device)
  (message "Device %s added" device))

(dbus-register-signal
 :system nil nil nil nil #'my-signal-handler)

But nope, total silence. And google shows me nothing, of course, because Google. I’ve been experimenting lately with using ChatGPT for somewhat vague questions like this, so I asked, and it gave me the same basic solution:

Which doesn’t work, either.

Now, I haven’t kept up with Emacs development, so I have no idea whether this has been fixed by now, but I looked at the source code in my Emacs, and:

Hey! The handlers are registered in a hash table! There’s no wildcarding for the interface and signal parameters!

And with that, I whipped up a little package (that you can find on Microsoft Github) that allows you to conveniently look at the Dbus properties that change:

Etc etc. And… tada! All the info for all my three problems is available!

So now 1) my laptops dims the screen when there’s 5% battery power left (livin’ on the edge), 2) switches off the screen when I close the lid, and 3) stops playing music when I switch off the bluetooth speaker (and switches the music back on again when I switch the speaker on).

Success! Everything is indeed possible if you have Emacs.

Now, the package on Microsoft Github can’t be used as is by anybody, because it’s so dependent on what your environment looks like. But I think it’s structured in a way that you can trivially tinker with it. So if you have any similar odd configuration issues (because you’ve got strange requirements), have at it.

6 thoughts on “Using Emacs to Monitor Dbus”

  1. Thank you for this example — using it as a starting point, I was finally able to automount a usb stick when I plug it in. A minor irritation that has plagued me for more than a decade.

  2. According to your problem with wildcards: bug#69926 has reported it, and with a recent checkout from master, it should work. The commit messages indicate it was fixed on March 31.

Leave a Reply