<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Muffin Research Labs &#187; Linux/Unix</title>
	<atom:link href="http://muffinresearch.co.uk/archives/category/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://muffinresearch.co.uk</link>
	<description>the personal blog of Stuart Colville covering modern web development techniques and best practices</description>
	<lastBuildDate>Thu, 15 Mar 2012 10:10:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Linux: Spotify Screensaver D-Bus Script update</title>
		<link>http://muffinresearch.co.uk/archives/2011/10/27/linux-spotify-screensaver-d-bus-script-update/</link>
		<comments>http://muffinresearch.co.uk/archives/2011/10/27/linux-spotify-screensaver-d-bus-script-update/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 22:07:37 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux/Unix]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1207</guid>
		<description><![CDATA[Following on from my previous post about a script to Pause and Play tracks on spotify based on the status of the screensaver as reported by D-Bus on a Linux Desktop, here&#8217;s an update: With the latest versions of Spotify on Linux (e.g: 0.6.1.309.gb871a7d0, 0.6.2.291.gcccc1f58) the DBus interface has changed a little which has resulted [...]]]></description>
			<content:encoded><![CDATA[<p>Following on from my <a href="http://muffinresearch.co.uk/archives/2010/11/03/spotify-screensaver-toggle-with-dbus/">previous post</a> about a script to Pause and Play tracks on spotify based on the status of the screensaver as reported by D-Bus on a Linux Desktop, here&#8217;s an update:</p>
<p>With the latest versions of Spotify on Linux (e.g: 0.6.1.309.gb871a7d0, 0.6.2.291.gcccc1f58) the DBus interface has changed a little which has resulted in the need to make some changes so that the playing status is tracked correctly.</p>
<p>The code can be found here on github as a <a href="https://gist.github.com/1320970">Gist</a> or the <a href="https://raw.github.com/gist/1320970/e117fc63de0ee231c44eb6a532353bbab364673d/spotify_dbus_screensaver.py">raw file.</a></p>
<p><script src="https://gist.github.com/1320970.js?file=spotify_dbus_screensaver.py"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/10/27/linux-spotify-screensaver-d-bus-script-update/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Linux: Spotify Track Notifier with added D-Bus love</title>
		<link>http://muffinresearch.co.uk/archives/2011/03/23/linux-spotify-track-notifier-with-added-d-bus-love/</link>
		<comments>http://muffinresearch.co.uk/archives/2011/03/23/linux-spotify-track-notifier-with-added-d-bus-love/#comments</comments>
		<pubDate>Wed, 23 Mar 2011 01:55:28 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux/Unix]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1135</guid>
		<description><![CDATA[I&#8217;ve recently updated the spotify notifier example I&#8217;d previously posted as an example along with my spotify screensaver script. First, I made an update to have it listen to the PropertiesChanged signal. Annoyingly for some unknown reason this signal isn&#8217;t visible in D-feet which had led to the erroneous assumption it wasn&#8217;t implemented. Implementing Album [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://mrl.staticfil.es/img/spotify-track-notifier.jpg" alt="spotify track notifier" /></p>
<p>I&#8217;ve recently updated the spotify notifier example <a href="http://muffinresearch.co.uk/archives/2010/11/03/spotify-screensaver-toggle-with-dbus/">I&#8217;d previously posted as an example along with my spotify screensaver script</a>. First, I made an update to have it listen to the <code>PropertiesChanged</code> signal. Annoyingly for some unknown reason this signal isn&#8217;t visible in D-feet which had led to the erroneous assumption it wasn&#8217;t implemented.</p>
<h3>Implementing Album Art</h3>
<p>After getting it working again, I started to think about how it would be nice to add album art. So I rigged up the script to the last.fm API to grab album art. I&#8217;d have preferred to pull the album art from spotify or via open.spotify.com, but annoyingly there doesn&#8217;t seem to be a way to get the album art url without scraping, which just seemed too much of a kludge. If anyone knows how to get album art from the spotify cache (assuming it&#8217;s there) then I&#8217;d be interested to hear about it.</p>
<h3>Listening for Spotify announcing itself on D-Bus</h3>
<p>Once I had that done, I then thought about how this script would run. Ideally it needs to run before spotify is necessarily open. This causes a problem though because if you try and listen for D-Bus events when the app in question isn&#8217;t running you&#8217;ll get an error.</p>
<p>So I used the <code>NameOwnerChanged</code> signal and listened for Spotify joining D-Bus and leaving it again. This then provided all that was needed to turn on or off the listener for the <code>PropertiesChanged</code> signal that fires when the track changes.</p>
<p>Also I added a check to try and set-up the <code>PropertiesChanged</code> listener at start-up in-case spotify is already running when the script is launched.</p>
<h3>The code</h3>
<pre><code>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Title: Spotify Notification Demo
Author: Stuart Colville, http://muffinresearch.co.uk
License: BSD

"""

import os
import dbus
import gobject
import pynotify
import httplib2
from urllib import quote
from cgi import escape
from xml.dom.minidom import parseString
from hashlib import md5
from dbus.mainloop.glib import DBusGMainLoop
from dbus.exceptions import DBusException

LASTFM_API_KEY = os.environ.get("LASTFM_API_KEY")
HTTP_CACHE_DIR = os.path.expanduser("~/.cache/spotify/http/")
IMAGE_CACHE_DIR = os.path.expanduser("~/.cache/spotify/art/")
BASE_URL = ("https://ws.audioscrobbler.com/2.0/?method=album."
            "getinfo&#038;api_key=%s&#038;artist=%%s&#038;album=%%s" % LASTFM_API_KEY)

MISSING = os.path.realpath(os.path.join(os.path.dirname(__file__), "missing.png"))

if not os.path.isdir(HTTP_CACHE_DIR):
    os.makedirs(HTTP_CACHE_DIR)
if not os.path.isdir(IMAGE_CACHE_DIR):
    os.makedirs(IMAGE_CACHE_DIR)

class SpotifyNotifier(object):

    def __init__(self):
        """initialise."""
        bus_loop = DBusGMainLoop(set_as_default=True)
        self.bus = dbus.SessionBus(mainloop=bus_loop)
        loop = gobject.MainLoop()
        self.http = httplib2.Http(HTTP_CACHE_DIR)
        self.notify_id = None
        try:
            self.props_changed_listener()
        except DBusException, e:
            if not ("org.mpris.MediaPlayer2.spotify "
                    "was not provided") in e.get_dbus_message():
                raise
        self.session_bus = self.bus.get_object("org.freedesktop.DBus",
                                 "/org/freedesktop/DBus")
        self.session_bus.connect_to_signal("NameOwnerChanged",
                                        self.handle_name_owner_changed,
                                        arg0="org.mpris.MediaPlayer2.spotify")

        loop.run()

    def props_changed_listener(self):
        """Hook up callback to PropertiesChanged event."""
        self.spotify = self.bus.get_object("org.mpris.MediaPlayer2.spotify",
                                           "/org/mpris/MediaPlayer2")
        self.spotify.connect_to_signal("PropertiesChanged",
                                        self.handle_properties_changed)

    def handle_name_owner_changed(self, name, older_owner, new_owner):
        """Introspect the NameOwnerChanged signal to work out if spotify has started."""
        if name == "org.mpris.MediaPlayer2.spotify":
            if new_owner:
                # spotify has been launched - hook it up.
                self.props_changed_listener()
            else:
                self.spotify = None

    def handle_properties_changed(self, interface, changed_props, invalidated_props):
        """Handle track changes."""
        metadata = changed_props.get("Metadata", {})
        if metadata:
            if pynotify.init("Spotify Notifier Demo"):

                title = unicode(metadata.get("xesam:title").encode("latin1"))
                album = unicode(metadata.get("xesam:album").encode("latin1"))
                artist = unicode(metadata.get("xesam:artist").encode("latin1"))
                hash_ = md5()
                hash_.update("%s-%s" % (artist, album))
                hash_path = hash_.hexdigest()
                image_path = os.path.join(IMAGE_CACHE_DIR, hash_path)
                if not os.path.exists(image_path):
                    url = BASE_URL % (escape(quote(artist.encode("utf8"))),
                                       escape(quote(album.encode("utf8"))))
                    response, content = self.http.request(url, "GET")
                    dom = parseString(content)
                    images = dom.getElementsByTagName("image")
                    for image in images:
                        for attr, value in image.attributes.items():
                            if attr == "size" and value == "medium":
                                image_url = None
                                if image and image.firstChild:
                                    image_url = image.firstChild.nodeValue
                                if image_url:
                                    response, image_contents = \
                                                self.http.request(image_url)
                                    if image_contents:
                                        fh = open(image_path, "w")
                                        fh.write(image_contents)
                                        fh.close()            

                if not os.path.exists(image_path):
                    image_path = MISSING

                alert = pynotify.Notification(title,
                              "by %s from %s" % (artist, album), image_path)
                if self.notify_id:
                    alert.props.id = self.notify_id
                alert.set_urgency (pynotify.URGENCY_NORMAL)
                alert.show()
                self.notify_id = alert.props.id

if __name__ == "__main__":
    SpotifyNotifier()</code></pre>
<h3>Pre-requisites</h3>
<ul class="ext">
<li><a href="http://www.spotify.com/uk/download/previews/">Spotify for Linux</a></li>
<li>A Spotify unlimited or premium account</li>
<li>Install httplib2: sudo apt-get install python-httplib2 (I think that&#8217;s the only dep that isn&#8217;t installed by default)</li>
<li>Set-up the script as outlined below.</li>
</ul>
<h3>Getting the code</h3>
<p>The code is available in a bzr branch here: <a href="http://code.projectfondue.com/stuart.colville/spotify-track-notify/files">code.projectfondue.com</a></p>
<p>To run it check it out and follow the notes in the README file. No doubt there might be some bugs so feel free to let me know of any possible improvements that can be made to it.</p>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/03/23/linux-spotify-track-notifier-with-added-d-bus-love/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Updating Vim to Use Plugins From Branches</title>
		<link>http://muffinresearch.co.uk/archives/2011/02/11/updating-vim-to-use-plugins-from-branches/</link>
		<comments>http://muffinresearch.co.uk/archives/2011/02/11/updating-vim-to-use-plugins-from-branches/#comments</comments>
		<pubDate>Fri, 11 Feb 2011 00:05:00 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux/Unix]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1101</guid>
		<description><![CDATA[I decided the other evening that I should refresh my vim plugins to pick up any updates that have landed since the last time I updated them. The downside is that every time I want to do this, I have the pain of manually re-installing the updated files into the various plugin directories to get [...]]]></description>
			<content:encoded><![CDATA[<p>I decided the other evening that I should refresh my vim plugins to pick up any updates that have landed since the last time I updated them. The downside is that every time I want to do this, I have the pain of manually re-installing the updated files into the various plugin directories to get the plugins updated. This is far from ideal, so this time I decided to do something about it. First I stripped out all of the old plugins from <code>~/.vim/plugins</code> and made a list of the plugin repos on github.</p>
<h3>Pathogen</h3>
<p><a href="https://github.com/tpope/vim-pathogen">pathogen</a> is a helper for modifying the runtimepath. This makes it possible to branch a plugin from github to <code>.vim/bundle</code> and then pathogen will ensure that it&#8217;s added to the runtime path.</p>
<p>To make this work first you need to download pathogen and place it in <code>.vim/autoload</code></p>
<p>Next add the following to your <code>.vimrc</code> file:</p>
<pre><code>call pathogen#runtime_append_all_bundles()</pre>
<p></code></p>
<p>Once you have done this simple check-out the branches of your favorite vim plugins to .vim/bundle and that's it.</p>
<h3>Scripting plugin updates</h3>
<p>To make life even easier I knocked up a very crude python script and Makefile to clone all my favorite plugins when I run "make get" and update them when I run "make update".</p>
<p>It's crude because currently it only cares about git (currently all the plugins I care about are on github) and it doesn't currently allow revs to be specified. Though both of these features could be fairly easily added. Anyway, in-case it's useful as a starting point to for someone else, here's the script:</p>
<p>Also if you're using git to version your branch (I'm not). Then you could use <a href="http://book.git-scm.com/5_submodules.html">git submodules</a> to achieve a similar effect.</p>
<pre><code>#!/usr/bin/env python

import os
import sys
import subprocess

BUNDLE_DIR = os.path.expanduser("~/.vim/bundle")

plugin_branches = {
    "git": [
        "git://github.com/tomtom/tlib_vim.git",
        "git://github.com/garbas/vim-snipmate.git",
        "git://github.com/scrooloose/nerdtree.git",
        "git://github.com/scrooloose/syntastic.git",
        "git://github.com/MarcWeber/vim-addon-mw-utils.git",
        "git://github.com/scrooloose/nerdcommenter.git",
    ],
}

def get():
    os.chdir(BUNDLE_DIR)
    for vcs_type, branches in plugin_branches.items():
        if vcs_type == "git":
            for branch in branches:
                subprocess.call(["git", "clone", branch])

def update():
    os.chdir(BUNDLE_DIR)
    for vcs_type, branches in plugin_branches.items():
        if vcs_type == "git":
            for branch in branches:
                subdir = os.path.split(branch)[-1][:-4]
                os.chdir(subdir)
                subprocess.call(["git", "pull"])
                os.chdir("../")

if __name__ == "__main__":
    args = sys.argv
    if args and len(args) > 1:
        if args[1] == "get":
            sys.exit(get())
        elif args[1] == "update":
            sys.exit(update())</pre>
<p></code></p>
<p>If you save this somewhere as deps.py you can then run it as <code>python deps.py get</code> and <code>python deps.py update</code>. I use a simple Makefile to do this.        </p>
<p>The code is deliberately structured to make it easy to modify if you wanted to add mercurial or bzr support. That is left as an excercise for the reader.</p>
<p>It's likely I will update this script in due course, to keep up to date with that and any other aspects of my vim conf you can get the whole thing from here: <a href="https://code.launchpad.net/~muffinresearch/+junk/dotvim">lp:~muffinresearch/+junk/dotvim</a></p>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/02/11/updating-vim-to-use-plugins-from-branches/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Android: Force Moving Apps to an SD Card</title>
		<link>http://muffinresearch.co.uk/archives/2011/02/02/android-force-moving-apps-to-an-sd-card/</link>
		<comments>http://muffinresearch.co.uk/archives/2011/02/02/android-force-moving-apps-to-an-sd-card/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 19:19:55 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Linux/Unix]]></category>
		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1081</guid>
		<description><![CDATA[This isn&#8217;t anything new but I thought I would share my experiences of trying to free space on my HTC desire by forcing apps to be movable to the sd card using the android SDK on linux. WARNING: Ensure you have a backup of any important data before you start in case something goes wrong. [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://mrl.staticfil.es/img/droids.png" alt="Droids Skateboarding" with="540" height="245" /></p>
<p>This isn&#8217;t anything new but I thought I would share my experiences of trying to free space on my HTC desire by forcing apps to be movable to the sd card using the android SDK on linux.</p>
<p><strong>WARNING</strong>: Ensure you have a backup of any important data before you start in case something goes wrong. Carrying out these instructions is at your own risk.</p>
<p>Running out of space is really the only annoyance I have come across since owning an android phone. Every now and again the low space icon comes up and you have to try and free up some space.</p>
<p>Since Froyo you&#8217;ve been able to move certain apps to SD card, but it&#8217;s only if the developer allows it. If you&#8217;re an android developer and you want to know how to do it, see this post: <a href="http://mobile.tutsplus.com/tutorials/android/move-to-sd-card/">Enabling the Android Move To SD Card Feature</a></p>
<p>So if you&#8217;re stuck with a bunch of apps you can&#8217;t move by default because &#8220;Move to SD Card&#8221; is greyed out in &#8220;Settings -> Applications -> Manage Applications -> Appname&#8221; then you might be thinking it&#8217;s not possible. However, <em>it is</em> possible to change the default install location to SD card via adb.</p>
<h3>Introducing the Android Debug Bridge</h3>
<p>Adb is the <a href="http://developer.android.com/guide/developing/tools/adb.html">Android Debug Bridge</a> which comes as part of the SDK. If you don&#8217;t have the SDK the first thing you will need to do is install it (get it from<a href="http://developer.android.com/sdk/index.html">developer.android.com</a>). Once you have the SDK you can find the adb tool in &lt;sdk&gt;/platform-tools/, though in my case I have it at &lt;sdk&gt;/tools/.</p>
<p class="update">Update 2012-01-26: You may find when you unpack the SDK adb isn&#8217;t there. If that&#8217;s the case you may need to run the &#8220;<code>android</code>&#8221; program (<code>./android</code> under linux) to be shown a window which provides a way to download platform-tools. once you have installed that you should find <code>adb</code> there.</p>
<p>After you&#8217;ve installed the SDK you&#8217;ll need to connect your phone to your computer using the USB data cable. You&#8217;ll also need to make sure that debugging is possible by visiting &#8220;Settings -> Applications -> Development&#8221; and checking &#8220;USB Debugging&#8221;.</p>
<h3>Enabling moving of apps to SD card</h3>
<p>To change the the install location we are going to run the pm command via the adb shell. Here&#8217;s the details of the pm command:</p>
<pre><code>The setInstallLocation command changes the default install location
  0 [auto]: Let system decide the best location
  1 [internal]: Install on internal device storage
  2 [external]: Install on external media</code></pre>
<p>To change the default install location to the SD card (which also enables moving most apps to the SD card.) run the following from the dir containing the adb command:</p>
<pre><code>./adb shell pm setInstallLocation 2</code></pre>
<p>If you at any point hit the following:</p>
<pre><code>error: insufficient permissions for device</code></pre>
<p>Try doing this:</p>
<pre><code>./adb kill-server
sudo ./adb  start-server</code></pre>
<p>You should now find you can run the above commands without error.</p>
<h3>Insufficient Storage Available</h3>
<p>The other error I had was that when I was trying to move any app after changing the default install location to the SD card was something along the lines of &#8220;Unable to move application. Insufficient Storage&#8221;.</p>
<p>The way I got around this was to uninstall twitter which was using about 17mb (it was the largest app). After that I re-installed it and it used far less space (naturally as the data would have been removed by the re-install process). After that I was able to successfully move most of my remaining apps (twitter included) to my SD card.</p>
<h3>Re-setting the installation location back to auto</h3>
<p>I&#8217;d strongly recommend re-setting the default installation location when you are done moving apps. The reason for this is that apps will fail to be installed directly to the external location, at least this is what I experienced when trying to re-install the twitter app.</p>
<p>To reset the install location to automatic (let the system decide) use the following:</p>
<pre><code>./adb shell pm setInstallLocation 0</code></pre>
<p>Should you forget where it was left at you can always run:</p>
<pre><code>./adb shell pm getInstallLocation</code></pre>
<p>e.g:</p>
<pre><code>$ ./adb shell pm getInstallLocation
0[auto]</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/02/02/android-force-moving-apps-to-an-sd-card/feed/</wfw:commentRss>
		<slash:comments>107</slash:comments>
		</item>
		<item>
		<title>Spotify ScreenSaver Toggle with D-bus</title>
		<link>http://muffinresearch.co.uk/archives/2010/11/03/spotify-screensaver-toggle-with-dbus/</link>
		<comments>http://muffinresearch.co.uk/archives/2010/11/03/spotify-screensaver-toggle-with-dbus/#comments</comments>
		<pubDate>Wed, 03 Nov 2010 00:10:39 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Linux/Unix]]></category>
		<category><![CDATA[Music]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1027</guid>
		<description><![CDATA[UPDATE! &#8211; see This post for the latest version of the spotify screensaver toggle The latest version of the spotify client for linux (0.4.8) has added partial mpris support. This is great as it means controlling spotify via D-bus is far easier than the previous hacks using wmctrl and xvkbd. I&#8217;ve updated the screensaver toggle [...]]]></description>
			<content:encoded><![CDATA[<p class="update">UPDATE! &#8211; see <a href="http://muffinresearch.co.uk/archives/2011/10/27/linux-spotify-screensaver-d-bus-script-update/">This post for the latest version of the spotify screensaver toggle</a></p>
<p>The latest version of the spotify client for linux (0.4.8) has added partial <a href="http://xmms2.org/wiki/MPRIS">mpris support</a>.</p>
<p>This is great as it means controlling spotify via D-bus is far easier than the previous hacks using <a href="http://muffinresearch.co.uk/archives/2010/09/13/ubuntu-spotify-screensaver-toggle/">wmctrl and xvkbd</a>. </p>
<p>I&#8217;ve updated the screensaver toggle script to use spotify&#8217;s D-bus interface to play/pause spotify. This also means that I&#8217;ve been able to de-couple the script from having to run the screensaver which a big improvement on the old version.</p>
<p>To run it just add the script to your start-up items.</p>
<p><img src="http://mrl.staticfil.es/img/startup_program.png" alt="Edit Startup Program Dialogue" /></p>
<p>Here&#8217;s the code, which is a lot more concise compared to the previous version.</p>
<p class="update">Updated to use Mpris2 as of <a href="http://code.projectfondue.com/stuart.colville/spotify-screensaver-toggle/revision/9">revision 9</a> for v0.4.8.306&#8230;</p>
<pre><code>#!/usr/bin/env python

"""
Title: Spotify Screensaver Toggle
Author: Stuart Colville, http://muffinresearch.co.uk/
License: BSD

Requires Spotify Linux Preview.

Usage:

 * Save the script
 * Ensure it is executable: chmod +x /path/to/script
 * Add the script to your start-up items. 

"""

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

class SpotifyScreenSaverPause(object):
    """This pauses and plays spotify when the screensaver is activated"""

    def __init__(self):
        """init class."""
        dbus_loop = DBusGMainLoop(set_as_default=True)
        self.bus = dbus.SessionBus(mainloop = dbus_loop)
        self.loop = gobject.MainLoop()
        self.start_listen()
        self.was_playing = 0
        self.loop.run()

    def start_listen(self):
        """Listen to screensaver ActiveChanged events from dbus."""
        screensaver = self.bus.get_object('org.gnome.ScreenSaver',
                                                  '/org/gnome/ScreenSaver')
        screensaver.connect_to_signal("ActiveChanged", self.play_pause)

    def play_pause(self, *args, **kwargs):
        """Toggle play/pause."""
        try:
            spotify = self.bus.get_object("org.mpris.MediaPlayer2.spotify", "/")
            spotify_iface = dbus.Interface(spotify, dbus_interface="org.freedesktop.MediaPlayer2")
            if self.was_playing:
                spotify_iface.Play()
                self.was_playing = 0
            else:
                if spotify_iface.GetMetadata():
                    self.was_playing = 1
                spotify_iface.Pause()
        except dbus.exceptions.DBusException, e:
            # Ignore exception caused by spotify not being started.
            if e.get_dbus_name() != 'org.freedesktop.DBus.Error.ServiceUnknown':
                raise

if __name__ == "__main__":
    ss = SpotifyScreenSaverPause()
</code></pre>
<p>See the latest version of the code here <a href="http://code.projectfondue.com/stuart.colville/spotify-screensaver-toggle/annotate/head:/spotify_dbus_screensaver">Spotify Screensaver Toggle</a> </p>
<p>If you want to investigate what&#8217;s possible with D-bus and spotify, <a href="http://live.gnome.org/DFeet/">D-feet</a> is an excellent tool for investigating D-bus:</p>
<p><a href="http://mrl.staticfil.es/img/d-feet-lg.png"><img src="http://mrl.staticfil.es/img/d-feet-sm.png" alt="D-feet D-bus Debugger" />Click for a larger version.</a></p>
<h3>Further Examples</h3>
<p>Here&#8217;s an example to get the metadata from a track currently playing. (Note: if Spotify isn&#8217;t playing this will be an empty dictionary.)</p>
<pre><code>>>> import dbus
>>> bus = dbus.SessionBus()
>>> spotify = bus.get_object("org.mpris.spotify", "/")
>>> spotify_iface = dbus.Interface(spotify, dbus_interface="org.freedesktop.MediaPlayer")
>>> spotify_iface.GetMetadata()
dbus.Dictionary({dbus.String(u'album'): dbus.String(u'Getz/Gilberto #2', variant_level=1), dbus.String(u'title'): dbus.String(u"Here's That Rainy Day", variant_level=1), dbus.String(u'artist'): dbus.String(u'Stan Getz', variant_level=1), dbus.String(u'year'): dbus.Int32(1964, variant_level=1), dbus.String(u'location'): dbus.String(u'spotify:track:1RIfT0Y0TwP2M38pLLfDeJ', variant_level=1), dbus.String(u'time'): dbus.UInt32(242L, variant_level=1), dbus.String(u'tracknumber'): dbus.Int32(4, variant_level=1)}, signature=dbus.Signature('sv'))
>>> print spotify_iface.GetMetadata().get("title")
Here's That Rainy Day
>>> print spotify_iface.GetMetadata().get("location")
spotify:track:1BTO5gV9xSAB7EOBKSlcFY
>>></code></pre>
<p class="update"><del datetime="2011-03-22T20:48:34+00:00">With the latest Spotify update to use MPRIS2 (0.4.8.306.xxx) &#8211; the TrackChanged signal has gone and there&#8217;s no PropertiesChanged signal as per MPRIS2 spec http://www.mpris.org/2.0/spec/ I&#8217;ll update the notification example script below as soon as that is rectified.</del><ins datetime="2011-03-22T20:48:34+00:00"> It was there all along. I&#8217;ve updated the code to reflect the use of PropertiesChanged</ins></p>
<p>To take that example further here&#8217;s a demo that listens to the <del datetime="2011-03-22T20:48:34+00:00">TrackChanged</del><ins>PropertiesChanged</ins> event. It uses the notification id so we can replace the notification details as you move through the tracks. This avoids waiting for the timeout before displaying the current track information.</p>
<pre><code>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Title: Spotify Notification Demo
Author: Stuart Colville, http://muffinresearch.co.uk
License: BSD

"""

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

class SpotifyNotifier(object):

    def __init__(self):
        """initialise."""
        bus_loop = DBusGMainLoop(set_as_default=True)
        bus = dbus.SessionBus(mainloop=bus_loop)
        loop = gobject.MainLoop()
        self.spotify = bus.get_object("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2")
        self.spotify.connect_to_signal("PropertiesChanged", self.track_changed)
        self.notify_id = None
        loop.run()

    def track_changed(self, interface, changed_props, invalidated_props):
        """Handle track changes."""
        metadata = changed_props.get("Metadata", {})
        if metadata:
            if pynotify.init("Spotify Notifier Demo"):

                title = unicode(metadata.get("xesam:title").encode("latin1"))
                album = unicode(metadata.get("xesam:album").encode("latin1"))
                artist = unicode(metadata.get("xesam:artist").encode("latin1"))

                alert = pynotify.Notification(title,
                                 "by %s from %s" % (artist, album))
                if self.notify_id:
                    alert.props.id = self.notify_id
                alert.set_urgency (pynotify.URGENCY_NORMAL)
                alert.show()
                self.notify_id = alert.props.id

if __name__ == "__main__":
    SpotifyNotifier()</code></pre>
<p>Note this notification demo assumes spotify is running to set-up the listener, so it&#8217;s not something you can just set running at start-up unless you use it to wrap the start-up of spotify.</p>
<p><img src="http://mrl.staticfil.es/img/spotify-notification.jpg" alt="Spotify Notifications of Track Changes" /></p>
<p>Both scripts are BSD licensed so feel free to use and adapt to your own purposes.</p>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2010/11/03/spotify-screensaver-toggle-with-dbus/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Fake SMTP server with Python</title>
		<link>http://muffinresearch.co.uk/archives/2010/10/15/fake-smtp-server-with-python/</link>
		<comments>http://muffinresearch.co.uk/archives/2010/10/15/fake-smtp-server-with-python/#comments</comments>
		<pubDate>Fri, 15 Oct 2010 22:17:38 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux/Unix]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1019</guid>
		<description><![CDATA[The other day a colleague was testing some code which relied on sending mail to a local mailserver and it was failing when the mailserver couldn&#8217;t be found. Needing to install postfix seemed overkill so I decided to look into what could be done to make a fake smtp service. All that was required was [...]]]></description>
			<content:encoded><![CDATA[<p>The other day a colleague was testing some code which relied on sending mail to a local mailserver and it was failing when the mailserver couldn&#8217;t be found. Needing to install postfix seemed overkill so I decided to look into what could be done to make a fake smtp service.</p>
<p>All that was required was something to pretend to be a real SMTP service as we didn&#8217;t need to view the messages at all.</p>
<p>Here&#8217;s the snippet I came up with using the smtpd module in Python:</p>
<pre><code>#!/usr/bin/env python
"""A noddy fake smtp server."""

import smtpd
import asyncore

class FakeSMTPServer(smtpd.SMTPServer):
    """A Fake smtp server"""

    def __init__(*args, **kwargs):
        print "Running fake smtp server on port 25"
        smtpd.SMTPServer.__init__(*args, **kwargs)

    def process_message(*args, **kwargs):
        pass

if __name__ == "__main__":
    smtp_server = FakeSMTPServer(('localhost', 25), None)
    try:
        asyncore.loop()
    except KeyboardInterrupt:
        smtp_server.close()</pre>
<p></code></p>
<p>To use this, save the above as fake_stmp.py and:</p>
<pre><code>chmod +x fake_smtp.py
sudo ./fake_smtp.py</code></pre>
<p>NOTE: Running this requires sudo to bind to port 25 as binding any port < 1024 requires superuser privileges.</p>
<p>Clearly you could easily adapt that to do something more useful if you want to see what's in the messages sent, either by writing messages to a file or printing them to stdout.</p>
<p>If printing them to stdout is what you need then there's also smtpd.DebuggingServer which is a subclass of SMTPServer which prints messages out to stdout. Using that is even easier and can be done with the following one liner:</p>
<pre><code>sudo python -m smtpd -n -c DebuggingServer localhost:25</code></pre>
<p>Again we use sudo in this case because we&#8217;re using port 25 if you don&#8217;t want that you can use a port higher than 1024.</p>
<p>To test this out we can use telnet like so:</p>
<pre><code>$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
220 localhost6.localdomain6 Python SMTP proxy version 0.2
HELO localhost
250 localhost6.localdomain6
MAIL FROM: test@test.com
250 Ok
RCPT TO: test@testing.com
250 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
subject: Hello
to: test@test.com
This is my message
.
250 Ok
QUIT
221 Bye
Connection closed by foreign host.</code></pre>
<p>Over on the terminal running the debugging server you should see the following:</p>
<pre><code>$ sudo python -m smtpd -n -c DebuggingServer localhost:25
[sudo] password for moo:
---------- MESSAGE FOLLOWS ----------
subject: Hello
to: test@test.com
This is my message
------------ END MESSAGE ------------</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2010/10/15/fake-smtp-server-with-python/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Inverting Screen Colours for Late-Night Hacking</title>
		<link>http://muffinresearch.co.uk/archives/2010/09/30/inverting-screen-colours-for-late-night-hacking/</link>
		<comments>http://muffinresearch.co.uk/archives/2010/09/30/inverting-screen-colours-for-late-night-hacking/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 23:24:01 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux/Unix]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1010</guid>
		<description><![CDATA[I&#8217;ve recently found it really hurts my eyes when working late at night going from a terminal (which is black background and light text) to a browser window like google.com with a large expanse of white. To help with this I&#8217;ve been looking for ways to reduce the screen brightness. The solution I&#8217;ve come up [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://mrl.staticfil.es/img/inverted-desktop-sm.png" width="540" height="338" alt="screenshot showing inverted colours"></p>
<p>I&#8217;ve recently found it really hurts my eyes when working late at night going from a terminal (which is black background and light text) to a browser window like google.com with a large expanse of white.</p>
<p>To help with this I&#8217;ve been looking for ways to reduce the screen brightness.</p>
<p>The solution I&#8217;ve come up with on Ubuntu is to use Compiz to invert the screen colours. If you open CompizConfig Settings Manager and look for Negative under Accessibility all you need to do is make sure it&#8217;s enabled and set a keystroke to toggle the inversion. By default it inverts everything within the window. However when you have terminals set to dark backgrounds like I do you don&#8217;t want those to be inverted and become glaring white backgrounds with dark text. Fortunately Compiz provides a feature to exclude certain windows.</p>
<p>Here&#8217;s an example for the &#8220;Exclude Windows&#8221; field to exclude the Desktop (a default), Guake and Gnome-terminal from being inverted.</p>
<pre><code>(type=Desktop) | class=Guake.py | class=Gnome-terminal</code></pre>
<p>If you use a mac you should be able to achieve the raw inversion with &#8220;Control Option Command 8&#8243;</p>
<p>Great. Now all I need is a silencer for my clacky keyboard!</p>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2010/09/30/inverting-screen-colours-for-late-night-hacking/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ubuntu: Spotify Screensaver Toggle</title>
		<link>http://muffinresearch.co.uk/archives/2010/09/13/ubuntu-spotify-screensaver-toggle/</link>
		<comments>http://muffinresearch.co.uk/archives/2010/09/13/ubuntu-spotify-screensaver-toggle/#comments</comments>
		<pubDate>Mon, 13 Sep 2010 11:21:50 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux/Unix]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=992</guid>
		<description><![CDATA[New version: I&#8217;ve updated the script to use D-bus with spotify for Linux version 0.4.8 see Spotify Screensaver Toggle with D-bus for further information. In a previous post, Lock Screen and Pause Spotify I provided a rudimentary script to pause spotify when your screensaver kicks in. Now with the Spotify Linux preview being available I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://mrl.staticfil.es/img/spotify-toggle/spotify-gd.jpg" alt="Spotify Interface" height="390" width="540" /></p>
<p class="update">New version: I&#8217;ve updated the script to use  D-bus with spotify for Linux version 0.4.8 see <a href="http://muffinresearch.co.uk/archives/2010/11/03/spotify-screensaver-toggle-with-dbus/">Spotify Screensaver Toggle with D-bus</a> for further information.</p>
<p>In a previous post, <a href="http://muffinresearch.co.uk/archives/2009/10/22/ubuntu-lock-screen-and-pause-spotify/">Lock Screen and Pause Spotify</a> I provided a rudimentary script to pause spotify when your screensaver kicks in. Now with the Spotify Linux preview being available I&#8217;ve started using (and paying for) a Spotify unlimited subscription. I decided I wanted to update the script to be able to pause Spotify when the screen is locked and also start playing after I log-in.</p>
<p>Initially I was hoping to do all of this by listening to Dbus events for when the screensaver is activated/deactivated. However, for some reason it&#8217;s not possible to play/pause spotify based on the DBus event saying that the screensaver is active (Presumably because it&#8217;s not possible to focus a window after the screensaver is active). Because of this current limitation the workaround is use this script to lock the screen for you. This way it locks the screen after it has set-up the listeners for the screensaver Dbus events.</p>
<p>When the screensaver is de-activated the script fires off the function to get Spotify playing again but <em>only</em> if it was playing before the screensaver was activated.</p>
<p>When spotify has an api, it will then make sense to use that instead, which should mean that this script can then be completely run by listening to dbus events which would be much more elegant.</p>
<h3>Dependencies</h3>
<p>The deps are the same as before &#8211; here&#8217;s the incantation to install them for Ubuntu.</p>
<pre><code>sudo apt-get install wmctrl xvkbd</code></pre>
<h3>Usage</h3>
<p>To set it up, link the script to somewhere in your path and then create a keystroke in  &#8220;System -> Preferences -> Keyboard Shortcuts&#8221; to lock the screen. Once that&#8217;s done, you should see the screen lock when that keystroke is executed and Spotify will be paused if it was playing.</p>
<p><img src="http://mrl.staticfil.es/img/spotify-toggle/keyboard-shortcut.png" alt="Keyboard Shortcut Dialogue" height="384" width="540" /></p>
<h3>Get the code</h3>
<p>You can <a href="http://code.projectfondue.com/stuart.colville/spotify-screensaver-toggle/files">grab the code from here</a>. Feel free to send me improvements or suggestions on how to make it better.</p>
<p class="update">Known issue: I&#8217;ve noticed a bug in that it doesn&#8217;t pause if the window is hidden. This is tricky as it&#8217;s not visible to the window list. Suggestions how to workaround this are welcomed.</p>
<h3>Additional thanks</h3>
<p><a href="http://sites.google.com/site/tommymattila/home/spotifycontrol">Tommy Mattila&#8217;s Spotify Control</a> which was based on my original script, provided useful insight into handling the active window. </p>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2010/09/13/ubuntu-spotify-screensaver-toggle/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Debugging Elusive Puppet Errors</title>
		<link>http://muffinresearch.co.uk/archives/2010/06/08/debugging-elusive-puppet-errors/</link>
		<comments>http://muffinresearch.co.uk/archives/2010/06/08/debugging-elusive-puppet-errors/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 18:14:04 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux/Unix]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=872</guid>
		<description><![CDATA[On working on some puppet manifests I hit this error message: $ sudo puppetd -t err: Could not retrieve catalog from remote server: undefined method `closed?' for nil:NilClass warning: Not using cache on failed catalog err: Could not retrieve catalog; skipping run Certainly not the most enlightening error message. After checking over the syntax of [...]]]></description>
			<content:encoded><![CDATA[<p>On working on some puppet manifests I hit this error message:</p>
<pre><code>$ sudo puppetd -t
err: Could not retrieve catalog from remote server: undefined method `closed?' for nil:NilClass
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run</code></pre>
<p>Certainly not the most enlightening error message. After checking over the syntax of my mainfests it still wasn&#8217;t obvious what was wrong.</p>
<p>First port of call to diagnose the problem is to try enabling debugging on the client:</p>
<p>On the <strong>client</strong>:</p>
<pre><code># Run the client with debugging enabled.
$ sudo puppetd -t --debug</code></pre>
<p>If that yields nothing useful try the following:</p>
<p>On the <strong>puppetmaster</strong> run:</p>
<pre><code># If it's running stop the puppetmasterd service
# change this to suit your distro - the following is debian specific
$ sudo /etc/init.d/puppetmaster stop 

# start the puppetmasterd in debug mode without daemonizing it.
$ sudo puppetmasterd --no-daemonize --debug</code></pre>
<p>Back on the <strong>client</strong> re-run the puppetd:</p>
<pre><code>$ sudo puppetd -t</code></pre>
<p>By looking at the debug output on the puppetmaster I was able to see my problem which was that a generate command didn&#8217;t have permission to write a necessary file. Once I&#8217;d fixed it everything worked as expected. </p>
<p>Once finished ctrl-c the foreground puppetmasterd and restart the service if you&#8217;d stopped it to run it in debug mode:</p>
<pre><code>$ sudo /etc/init.d/puppetmaster start</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2010/06/08/debugging-elusive-puppet-errors/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ubuntu: java.net.SocketException in ec2-api-tools</title>
		<link>http://muffinresearch.co.uk/archives/2010/06/04/ubuntu-java-net-socketexception-in-ec2-api-tools/</link>
		<comments>http://muffinresearch.co.uk/archives/2010/06/04/ubuntu-java-net-socketexception-in-ec2-api-tools/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 12:11:58 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Linux/Unix]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=891</guid>
		<description><![CDATA[Having installed ec2-api-tools under my lucid dev environment I was trying to shut ec2 instances down with ec2stop [instance_id] and I was getting the following exception: $ ec2stop i-XXXXXXXX Unexpected error: java.net.SocketException: Invalid argument or cannot assign requested address at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:310) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:176) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:163) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:384) ----- snip ------ I found [...]]]></description>
			<content:encoded><![CDATA[<p>Having installed ec2-api-tools under my lucid dev environment I was trying to shut ec2 instances down with ec2stop [instance_id] and I was getting the following exception:</p>
<pre><code>$ ec2stop i-XXXXXXXX
Unexpected error:
java.net.SocketException: Invalid argument or cannot assign requested address
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:310)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:176)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:163)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:384)
        ----- snip ------</code></pre>
<p>I found to enable ec2-api-tools commands to work it&#8217;s necessary to switch over to using the sun jre. </p>
<p>Note: In lucid open-jdk is the default java and sun-java6-jre is now found in the partner repos. </p>
<p>You can do this if you have the sun-java6-jre package with the following:</p>
<pre><code>sudo update-alternatives --config java</code></pre>
<p>And select the correct version interactively.</p>
<p>Should you need to add the Lucid partner repo you can use the following:</p>
<pre><code>sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2010/06/04/ubuntu-java-net-socketexception-in-ec2-api-tools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

