Controlling vagalume last.fm client using python

I've recently been playing with the docky python bindings, and started by writing a helper to interact with Vagalume, a lightweight last.fm client (I later added it to a project on launchpad). The vagalume DBus methods and signals are mostly undocumented, but they can be found lurking around after a quick look at some of the source code.

import dbus
import gobject
from dbus.mainloop.glib import DBusGMainLoop

class Vagalume(object):
    def __init__(self):
        dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
        self.bus = dbus.SessionBus()

        self.player = self.bus.get_object('com.igalia.vagalume',
                                          '/com/igalia/vagalume')

        self.bus.add_signal_receiver(self.song_changed,
                                     dbus_interface='com.igalia.vagalume',
                                     signal_name='notify')

    def song_changed(self, *args):
        state = args[0]
        if state == 'stopped':
            #do something when the player is stopped
            self.stopped()
        elif state == 'playing':
            artist = args [1]
            title = args [2]
            album = args [3]
            #do something with the data here...
            self.playing(artist, title, album)

    def stopped(self):
        '''Run when music is stopped'''
        pass

    def playing(self, artist, title, album):
        '''Run when new song is played'''
        pass

if __name__ == "__main__":
    app = Vagalume()

    # gtk mainloop can be used if you're using this as part of a gtk app
    mainloop = gobject.MainLoop(is_running=True)
    mainloop.run()

You'll probably notice the method song_changed. This is a method which is registered with DBus and run each time the 'notify' signal is emitted from vagalume. This checks whether the notification is due to vagalume starting a new song or stopping the current one and runs either self.stopped or self.playing. These two methods by default do nothing, so subclassing Vagalume to make them do something useful is good:

class MyFancyVagalume(Vagalume):
    def stopped(self):
        print 'just stopped the beat'

    def playing(self, artist, title, album):
        print 'now playing "%s" by %s' % (title, artist)

To interact with vagalume do something like:

vagalume = Vagalume()

# do anything you want with dbus
vagalume.player.Play()
vagalume.player.Skip()
vagalume.player.LoveTrack()
vagalume.player.BanTrack()
vagalume.player.Stop()

take a look at the source (http://gitorious.org/vagalume/vagalume/blobs/master/src/dbus.h) for all of the functions available


Grabbing screenshots as a Python Image Library Image type

A couple of days ago I needed to take screenshots of my linux desktop's screen and manipulate these captured images using Python Image Library (PIL). I wrote a small python class to do the work of taking the screenshot and returning a PIL Image object for use in the rest of the system I was writing.

The code ended up being simpler than I expected, mostly because GDK, the library used as an intermediary between GTK and the low-level window manager and display server commands, does all the heavy lifting.

Method

I wanted to take many screenshots during a run of the program I was writing, so allocated a persistent gtk.gdk.Pixbuf object to store the captured image in. This object has a handy get_from_drawable method. Of course, the X11 root window is a drawable, so by using gtk.gdk.get_default_root_window() we can copy each pixel into our buffer.

Once the Pixbuf is full, an Image needs to be created from it, since that was the original aim. Luckily, there's Image.frombuffer to do all the hard work when combined with Pixbuf.get_pixels().

Full code:

import Image, gtk

class Screenshotter(object):
    def __init__(self):
        self.img_width = gtk.gdk.screen_width()
        self.img_height = gtk.gdk.screen_height()

        self.screengrab = gtk.gdk.Pixbuf(
            gtk.gdk.COLORSPACE_RGB,
            False,
            8,
            self.img_width,
            self.img_height
        )

    def take(self):
        self.screengrab.get_from_drawable(
            gtk.gdk.get_default_root_window(),
            gtk.gdk.colormap_get_system(),
            0, 0, 0, 0,
            self.img_width,
            self.img_height
        )

        final_screengrab = Image.frombuffer(
            "RGB",
            (self.img_width, self.img_height),
            self.screengrab.get_pixels(),
            "raw",
            "RGB",
            self.screengrab.get_rowstride(),
            1
        )

        return final_screengrab

if __name__ == '__main__':
    screenshot = Screenshotter()
    image = screenshot.take()

© Louis Taylor. Index ¦ Archives ¦ Pelican ¦ Theme.