Will's blog

purpose: Will Kahn-Greene's blog of Miro, PyBlosxom, Python, GNU/Linux, random content, PyBlosxom, Miro, and other projects mixed in there ad hoc, half-baked, and with a twist of lemon

[ home | blog home | recent activity ]

Mon, 25 Jan 2010

Handling media keys in GNOME with Python

Spent a while figuring out how to get Miro to handle media keys in Gnome. My current understanding (and this could be entirely wrong) is that as of 2.18, Gnome handles the multimedia keys. In order for your application to respond to multimedia keys, you have to connect to the signal through dbus.

My biggest problem is that my web searching revealed a lot of bugs, but no documentation. I did finally find Handling multimedia keys in GNOME 2.18 and then worked out the rest. I still have no clue where to find the documentation for it.

Here's what I got working:

import logging
import dbus

from miro import app

class MediaKeyHandler(object):
    def __init__(self, window):
        self.app = "Miro"
        self.bus = dbus.Bus(dbus.Bus.TYPE_SESSION)
        self.bus_object = self.bus.get_object(
            'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/MediaKeys')

        self.bus_object.GrabMediaPlayerKeys(
            self.app, 0, dbus_interface='org.gnome.SettingsDaemon.MediaKeys')

        self.bus_object.connect_to_signal(
            'MediaPlayerKeyPressed', self.handle_mediakey)

        window.connect("focus-in-event", self.on_window_focus)

    def handle_mediakey(self, application, *mmkeys):
        if application != self.app:
            return
        for key in mmkeys:
            if key == "Play":
                app.widgetapp.on_play_clicked()
            elif key == "Stop":
                app.widgetapp.on_stop_clicked()
            elif key == "Next":
                app.widgetapp.on_forward_clicked()
            elif key == "Previous":
                app.widgetapp.on_previous_clicked()

    def on_window_focus(self, window):
        self.bus_object.GrabMediaPlayerKeys(
            self.app, 0, dbus_interface='org.gnome.SettingsDaemon.MediaKeys')
        return False

def get_media_key_handler(window):
    """
    Creates and returns a MediaKeyHandler or returns None if such a thing
    is not available on this platform.

    :param window: a Gtk.Window instance
    """
    try:
        return MediaKeyHandler(window)
    except dbus.DBusException:
        logging.exception("cannot load MediaKeyHandler")

If you see problems with this, let me know so I can ammend the code.

November 5th, 2010 - Fixed a bug in the code.
November 9th, 2010 - Tweaked the code to re-assert key handling on focus.

Comments:

Posted by Marius Gedminas on Tue Jan 26 02:10:55 2010
So, what happens when there are two apps with this kind of code running?  Will both process the Play key and start playing different things at the same time?


Posted by will on Thu Jan 28 10:13:27 2010
Marius: I'm pretty sure that's what the first argument GrabMediaKeys allows for.  I'm not sure what happens if two media applications send in 0, though.  I wish there was documentation for it or I knew where the code was so I could go read it.


Posted by Jean-Lou Dupont on Sun Feb 20 11:13:14 2011
Hi - great article... thanks!

How would you handle the "volume up / down" mediakeys then?


Posted by Sean Neakums on Sat Sep 17 04:21:09 2011
I had a poke around recently and found this comment above gsd_media_keys_manager_grab_media_player_keys() in plugins/media-keys/gsd-media-keys-manager.c from gnome-settings-daemon 3.1.91:

/*
* Register a new media player. Most applications will want to call
* this with time = GDK_CURRENT_TIME. This way, the last registered
* player will receive media events. In some cases, applications
* may want to register with a lower priority (usually 1), to grab
* events only nobody is interested.
*/

And in gdk/gdktypes.h:

#define GDK_CURRENT_TIME  0L

So 0 is the correct value to use after all.


Post a new comment:

Three things:

  1. New comments get placed in a "draft" status and will NOT show up on the site until I explicitly approve it. Sometimes that happens within 24 hours.
  2. I reserve the right to reject/remove inappropriate comments.
  3. Sometimes I'll reply to a comment directly in email--so make sure your email address is correct.

If you can't for some reason post a comment, send me an email: willg at bluesock dot org.

Your name:


Your e-mail address (this doesn't get displayed to anyone--sometimes I'll reply directly to you):


URL of your website (optional):


Comment:


Yes, I am a human!


pyblosxom::1.5-dev git-master

Copyright 1996 to 2012, Will Guaraldi Kahn-Greene, under the Creative Commons BY-SA 3.0 license

Creative Commons License
Will's Blog by William Kahn-Greene is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.