More fun with dbus

Since my dbus post last week, I’ve been playing around more with dbus whenever I get a few minutes. The modern Linux desktop is pretty good, but with minor tweaks, you can make things even better. (all this code is now up in a mercurial repository called dbus-hackery).

Automating Inactivity

Pidgin makes sounds on every message to me, xchat makes sounds on certain key words. Without these cues, I’d never remember to go check these applications. Because I have a tendency to leave my laptop on overnight, I found that I’d often have xchat ringing away at midnight when someone was looking for me. If I forgot to mute my machine before that, it would often wake me up.

One of the programs sending signals on dbus is gnome-screensaver.

def connect_screensaver(session_bus)
    ss_dbus = session_bus.service("org.gnome.ScreenSaver")
    ss = ss_dbus.object("/org/gnome/ScreenSaver")
    ss.introspect
    if ss.has_iface? "org.gnome.ScreenSaver"
        ss.default_iface = "org.gnome.ScreenSaver"
        puts "Connected to screensaver"
    end
    return ss
end

def mute()
    IO.popen("aumix -vq") {|r|
        r.read.scan(/(d+)/) {|m|
            @@vol = m
            puts "saved volume: #{@@vol}"
            break
        }
    }
    puts "muting"
    system("aumix -v 0")
end

def unmute()
    puts "unmuting"
    system("aumix -v #{@@vol}")
end

ss = connect_screensaver(session_bus)

ss.on_signal("ActiveChanged") {|s|
    if s
        mute
    else
        unmute
    end
}

The connect will look exactly as expected from the previous look at dbus. The ActiveChanged signal outputs a single parameter, a boolean, which is true when the screensave goes active, false when the screensaver is deactivated.

Volume control on the command line is most easily done with aumix (though if you are on Ubuntu Gutsy you’ll have issues until you rebuild aumix yourself. Hopefully they’ll fix that bug soon.) A little regex fun captures the current levels to a package variable, and restores them back on unmute.

Now I’ve got global mute when the screensaver fires, restored when I return.

Better Away with Pidgin

My screensaver being locked is a pretty clear indication that I’m away, though it being unlocked isn’t a clear indication that I’m back. Especially on weekends, I pop back for a quick check of something, then the computer is put away again.

def set_away(pidgin)
    puts "trying to set away"
    name = "screensaver"
    status = pidgin.PurpleSavedstatusFind(name)[0]
    if not status > 0
        status = pidgin.PurpleSavedstatusNew(name, 5)[0]
    end
    puts "Status #{status}"

    pidgin.PurpleSavedstatusSetMessage(status, "screen saver auto away")
    pidgin.PurpleSavedstatusActivate(status)
end

ss.on_signal("ActiveChanged") {|s|
    if s
        mute
        set_away(pidgin)
    else
        unmute
    end
}

In order to set a status with a message, it has to be a saved status. To prevent growing that to infinity, I first look to see if it is defined, creating a new saved status if not. 5 is a magic number here meaning STATUS_AWAY (reference the pidgin status.h for more info). Then we set the message on that status, and activate it. A single line change on our screen saver signal adds this into play.

Keep on Hacking

One of the things I’m hoping to impress in these posts on dbus is that with a highly functional language like ruby, linking applications on a modern gnome desktop can be done even by mere mortals. Linking sound to your screen saver is something that would have required a reasonable chunk of c code. Now you can do it in 20 lines of ruby, thanks to dbus.

I’ve thought about creating some sort of extended control panel to enable the features I’ve hacked together, but the reality is the code is so small, and so simple, it seems like overkill. With code this easy, you should just jump in and hack it to your own needs.

As I keep playing with dbus, I’ll post more bits here. Twitter integration is still on my list of things to do, and maybe something I’ll even manage to get to this week.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s