#!/usr/bin/python import logging import urllib import sys import time import optparse from lxml import etree from Growl import GrowlNotifier API_KEY="REPLACE_WITH_YOUR_API_KEY" class Roar(): """ Simple class to query the last.fm api for the currently playing song for a user and show the artist and title using Growl Note: I know that the data also is availble in json format, removing the need for lxml, but the json serialization is ugly as sin.... """ def __init__(self, user): logging.debug("Creating Roar client for user '%s'" % user) self._last_artist = None self._last_title = None api_data = { "user": user, "method": "user.getrecenttracks", "nowplaying": "true", "limit": "1", "api_key": API_KEY, } self._url = "http://ws.audioscrobbler.com/2.0/?" + urllib.urlencode(api_data) self._growler = GrowlNotifier(applicationName='Roar', notifications=["info"]) self._growler.register() def _get(self, node): """Get node text helper""" return node.text if node is not None else None def run(self, interval): """Fetch data indefinitely each 'internal' seconds""" while True: self.fetch() time.sleep(interval) def fetch(self): """Fetch data and notify if it has changed since last call""" logging.debug("Calling API") try: response = urllib.urlopen(self._url) except IOError, e: logging.warning("Got error opening API url: " + e) return if (response.getcode() != 200): logging.warning("Response error: %d" % response.getcode()) return xml = etree.parse(response) track = xml.xpath("//track[@nowplaying='true']") if not len(track): logging.debug("No currently playing track") return track = track[0] title = self._get(track.find("name")) or "Unknown Title" artist = self._get(track.find("artist")) or "Unknown Artist" if title == self._last_title and artist == self._last_artist: logging.debug("Nothing changed") return self._last_artist = artist self._last_title = title icon_url = self._get(track.find("image[@size='medium']")) icon = None if icon_url: logging.debug("Fetching icon (%s)" % icon_url) try: icon = urllib.urlopen(icon_url).read() except IOError, e: logging.warning("Could not fetch URL: " + e) logging.debug("Notifying: %s - %s" % (artist, title)) self._growler.notify("info", title, artist, icon=icon) if __name__ == "__main__": parser = optparse.OptionParser() parser.add_option("-d", "--debug", action="store_true", dest="debug", default=False, help="Turn on debugging") parser.add_option("-i", "--interval", type="int", dest="interval", default=30, help="Update interval, in seconds") (options, args) = parser.parse_args() if options.debug: logging.basicConfig(level=logging.DEBUG) if len(args) < 1: print "ERROR: Please give last.fm user name as the first argument\n" parser.print_help() exit() r = Roar(args[0]) r.run(options.interval)