<?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; Code</title>
	<atom:link href="http://muffinresearch.co.uk/archives/category/code/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, 26 Jan 2012 00:14:24 +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>Recover Files from Nandroid Backup</title>
		<link>http://muffinresearch.co.uk/archives/2011/10/27/recover-files-from-nandroid-backup/</link>
		<comments>http://muffinresearch.co.uk/archives/2011/10/27/recover-files-from-nandroid-backup/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 22:42:24 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1216</guid>
		<description><![CDATA[I recently flashed my Htc Desire with CyanogenMod 7.1 and I have to say it&#8217;s great to be free of htc sense. Given the rigmarole around the official Gingerbread update for the Desire I don&#8217;t think my next phone will be an htc one. Anyhow, prior to installing CM 7.1 I&#8217;d carefully made a nandroid [...]]]></description>
			<content:encoded><![CDATA[<p>I recently flashed my Htc Desire with CyanogenMod 7.1 and I have to say it&#8217;s great to be free of htc sense. Given the <a href="http://crave.cnet.co.uk/mobiles/htc-desire-gingerbread-update-available-if-youre-feeling-brave-50004594/">rigmarole around the official Gingerbread update</a> for the Desire I don&#8217;t think my next phone will be an htc one. </p>
<p>Anyhow, prior to installing CM 7.1 I&#8217;d carefully made a nandroid backup with ClockWorkMod recovery. Having set everything up I chose a ringtone + notification sound. Having lived with it for a bit I realised I miss the old sounds from the stock desire rom. To recover them I needed to mount extract the system.img file and then push the old audio files to the correct place.</p>
<p class="update">Warning: Please follow these steps at your own risk!</p>
<h3>Compiling unyaffs</h3>
<p>To extract .img files you&#8217;ll need <a href="http://code.google.com/p/unyaffs/">unyaffs</a> which can extract the files from a yaffs file system image. First copy the .img file into a directory. (For me the Nandroid img files were found in clockworkmod/backup/&lt;date&gt;/&lt;foo&gt;.img on the sdcard)</p>
<p>To compile unyaffs grab the unyaff.c and unyaffs.h from http://code.google.com/p/unyaffs/downloads/list and compile it with:</p>
<pre><code>gcc -o unyaffs unyaffs.c</code></pre>
<p>Once you&#8217;ve done that and added it to your path (alternatively copy it to /usr/local/bin).</p>
<p>Navigate to the directory containing the yaff img and run:</p>
<pre><code>./unyaffs system.img</code></pre>
<p>This will un-pack the files into that directory. </p>
<h3>Getting Files onto a Rooted Phone</h3>
<p>Once you have the files the next step is to get them onto your phone. To do that you&#8217;ll need the <a href="http://developer.android.com/sdk/index.html">Android SDK to be installed and set-up</a>.</p>
<p>When the SDK is there, connect your phone with the USB cable (with USB debugging enabled &#8211; Settings->Application->Development) run the following from the sdk&#8217;s platform-tools directory. </p>
<pre><code>./adb reboot recovery</code></pre>
<p>When the phone reboots to recovery mount the system partition.</p>
<p>Next as an example here&#8217;s the command I ran to copy the ringtones from the desire rom onto the phone:</p>
<pre><code>./adb remount
./adb push /home/bungle/desire-system/media/audio/ringtones /system/media/audio/ringtones</code></pre>
<p>This will copy all the files in the ringtones dir onto the phone.</p>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/10/27/recover-files-from-nandroid-backup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>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>Taking Screenshots of your Android Phone</title>
		<link>http://muffinresearch.co.uk/archives/2010/09/07/taking-screenshots-of-your-android-phone/</link>
		<comments>http://muffinresearch.co.uk/archives/2010/09/07/taking-screenshots-of-your-android-phone/#comments</comments>
		<pubDate>Tue, 07 Sep 2010 22:24:44 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Mobile]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=981</guid>
		<description><![CDATA[Annoyingly it&#8217;s far from trival to take screenshots of your android phone unless you&#8217;ve rooted your phone already in which case there are several apps on the market which provide this feature. This post focuses on what is currently the only alternative. DDMS stands for the Dalvik Debug Monitor Server. It provides various facilities to [...]]]></description>
			<content:encoded><![CDATA[<p>Annoyingly it&#8217;s far from trival to take screenshots of your android phone unless you&#8217;ve rooted your phone already in which case there are several apps on the market which provide this feature. This post focuses on what is currently the only alternative.</p>
<p>DDMS stands for the Dalvik Debug Monitor Server. It provides various facilities to debug applications on you phone.</p>
<h3>Enable USB Debugging</h3>
<p>To use it first you need to, enable debugging via USB. To do that open the settings app. From there navigate to &#8220;Applications&#8221;, in there select the &#8220;Development&#8221; option and then tick &#8220;USB Debugging&#8221;.</p>
<p><a href="http://mrl.staticfil.es/img/ddms/settings_l.png" title="Click image to see larger version"><img src="http://mrl.staticfil.es/img/ddms/settings_s.png" alt="Screenshot of USB Debug settings" /></a></p>
<h3>Connect your phone</h3>
<p>Next Connect your phone with the USB cable. Disk Mode is fine for this purpose.</p>
<h3>Get a copy of the SDK</h3>
<p>If you don&#8217;t already have a copy of the Android SDK you can get one from the <a href="http://developer.android.com/sdk/">SDK downloads page</a>.</p>
<p>Once you have this unpack it.</p>
<h3>Running DDMS</h3>
<p>To run ddms you should be able to run from the tools directory ddms directly e.g:</p>
<pre><code>./ddms</code></pre>
<p>If you can see you phone connected then all that&#8217;s left to do is select it and then select  Device -> Screen capture.</p>
<p>However if you just see unknown device with lots of question marks like I did then you&#8217;ll need to start the android debug bridge.</p>
<p><a href="http://mrl.staticfil.es/img/ddms/no-adb-l.png" title="Click image to see larger version"><img src="http://mrl.staticfil.es/img/ddms/no-adb-s.png" alt="Screenshot of no connection to device" /></a></p>
<p>To do this run the following from the sdk tools directory after shutting ddms down:</p>
<pre><code>sudo ./adb kill-server
sudo ./adb start-server</code></pre>
<p>Once it&#8217;s running open ddms again:</p>
<pre><code>./ddms</code></pre>
<p><a href="http://mrl.staticfil.es/img/ddms/debug_conn.png" title="Click image to see larger version"><img src="http://mrl.staticfil.es/img/ddms/debug_conn_s.png" alt="Screenshot of connection made" /></a></p>
<p>You should now see the device connected. Now you can select the device and then hit Device -> Screen capture.</p>
<p>The following window should open up:<br />
<img src="http://mrl.staticfil.es/img/ddms/screen_cap.png" alt="Screenshot of screen capture window" /></p>
<p>With that open you can then open any apps that you need to and just press refresh to get the current screen. Once you have the shot that you wanted press save and that&#8217;s all there is to it. I&#8217;m looking forward to there being a simple app to do this that doesn&#8217;t require root!</p>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2010/09/07/taking-screenshots-of-your-android-phone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Development Workflow</title>
		<link>http://muffinresearch.co.uk/archives/2010/07/28/development-workflow/</link>
		<comments>http://muffinresearch.co.uk/archives/2010/07/28/development-workflow/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 02:10:23 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=914</guid>
		<description><![CDATA[Photo CC licensed by oedipusphinx I&#8217;ve been working for canonical for about four and a half months now. One of the things that I&#8217;ve been really impressed with is the workflow for development and the process for how new features end up in trunk. The workflow is as follows: Feature Development Our primary development focus [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://mrl.staticfil.es/img/branches.jpg" alt="" height="252" width="540" /></p>
<p class="photo_cap">Photo CC licensed by <a href="http://www.flickr.com/photos/oedipusphinx/4425295409/">oedipusphinx</a></p>
<p>I&#8217;ve been working for <a href="http://canonical.com/">canonical</a> for about four and a half months now. One of the things that I&#8217;ve been really impressed with is the workflow for development and the process for how new features end up in trunk.</p>
<p>The workflow is as follows:</p>
<h2>Feature Development</h2>
<p>Our primary development focus is trunk as this is what&#8217;s deployed on a weekly basis. So the first step is to pull the local copy of trunk to ensure it&#8217;s up to date. Next, the developer makes a branch of trunk for the feature/bugfix.</p>
<pre><code>cd trunk
bzr pull
cd ../
bzr branch trunk branches/my-awesome-feature</code></pre>
<p>The feature is developed with <acronym title="test driven development">TDD</acronym> (tests first, followed by code to make the tests pass). Once the feature or bugfix is finished the branch is pushed up to launchpad under the project. </p>
<pre><code># hack hack hack
# Ensure tests pass
bzr push lp:~&lt;USER&gt;/&lt;PROJECT&gt;/&lt;BRANCHNAME&gt;</code></pre>
<p>A nice feature of bzr that I&#8217;d not used prior to working at canonical is the way you can automatically set push targets for branches based on the directory that contains them. So for example we have a config in <code>~/.bazaar/locations.conf</code> that looks something like this (obviously substituting the variables in angled brackets for your username and project etc):</p>
<pre><code>[/path/to/branches/]
push_location = bzr+ssh://&lt;USERNAME&gt;@bazaar.launchpad.net/~&lt;USERNAME&gt;/&lt;PROJECT&gt;
push_location:policy = appendpath</code></pre>
<p>So if I have a new branch at <code>/path/to/branches/foo-bar-baz</code></p>
<p>This will automatically set the push location to:</p>
<pre><code>bzr+ssh://&lt;USERNAME&gt;@bazaar.launchpad.net/~&lt;USERNAME&gt;/&lt;PROJECT&gt;/foo-bar-baz</code></pre>
<p>Meaning all I have to do is use <code>bzr push</code> to send my branch into launchpad.</p>
<p class="update">Note: At any time you can check the push location with <code>bzr info</code></p>
<h2>Code Review</h2>
<p>The next stage is for the developer to make a &#8220;merge proposal&#8221; via the launchpad interface. This puts the merge request in a &#8220;to be reviewed queue&#8221; which provided a merge proposal page with a diff of the changes from trunk (the target branch is customisable). The rule is that every branch has to be approved by a minimum of two devs. Reviewers can make recommendations or assert that something needs to be fixed and the developer can then push subsequent changes to the same branch and those changes are made visible.</p>
<p>The focus of reviews are on coding style, standards e.g. adherence to PEP 8, and reviewers will run the test suite and run pylint to check for any glaring violations. Merging with trunk is also carried out to check that no conflicts occur.</p>
<h3>Landing branches</h3>
<p>Once the code has been successfully reviewed code is submitted via <a href="https://edge.launchpad.net/bzr-pqm">PQM (Patch Queue Manager)</a> which then runs the test suite and only merges the code with trunk if the tests pass. We&#8217;re still using PQM but most projects have already begun the process to move to <a href="https://edge.launchpad.net/tarmac">tarmac</a> which is tightly integrated to launchpad.</p>
<p>I like the rigorous review process. By having code reviews a mandatory part of the process it becomes just part of a routine, everyone is used to it and so are happy to receive and give criticism. Reviews are definitely seen as a route to better code rather than making people feel small which is exactly how it should be. </p>
<p>The process might sound quite lengthy but because of the ease of branching in bzr (like any other <acronym title="Distributed Version Control System">DVCS</acronym>) the process is very quick and easy and branches are continually landed in trunk every day. It&#8217;s actively encouraged that branches are kept around 500 lines of diff where possible, to make it easier for code to get reviewed. Branches aren&#8217;t worked on for weeks on end, they are developed, reviewed and merged within what&#8217;s usually at most a couple of days.</p>
<h3>Future changes</h3>
<p>One of the things we&#8217;re currently looking at is using <a href="http://hudson-ci.org/">hudson</a> to automate the running of the test-suite for merge-proposals. This would mean that hudson could run the tests as soon as a merge proposal is made and provide an &#8220;approval&#8221; or &#8220;needs fixing&#8221; status based on the results of running the test suite. The net effect would be that we&#8217;d then require 3 approvals rather than 2.</p>
<h3>Summary</h3>
<p>Obviously our workflow revolves around the use of launchpad, but there&#8217;s plenty of ways to adopt a similar workflow without requiring the use of launchpad. For example on personal projects I&#8217;ve adopted pretty much the same process except branches are pushed to remote server instead of launchpad and <a href="http://code.google.com/p/rietveld/">rietveld</a> has been used for reviews in place of the merge proposal feature. Rietveld is fairly vcs-agnostic however, if you&#8217;re using git as your vcs then something like <a href="http://code.google.com/p/gerrit/">gerrit</a> might be worth looking at. (gerrit was originally a fork of rietveld but has more recently been completely re-written using java instead of python). Also <a href="http://www.reviewboard.org/">review-board</a> is another code review tool that works for all popular VCSs &#8211; review-board is django-based and is therefore relatively easy to set-up.</p>
<p>In summary:</p>
<ul class="ext">
<li>Use a <acronym title="Distributed Version Control System">DVCS</acronym> (e.g: git, mecurial, bzr) so branching is easy. I remember at Yahoo when CVS was the VCS everyone had to use, branching was explicitly avoided as much as possible because merging was seen as such a pain. Worst case, if you&#8217;re stuck with something like svn be comfortable with merging so branching is not a hurdle.</li>
<li>Branch as often as necessary.</li>
<li>Review everything and make it a part of the code routine.</li>
<li>Merge as early as possible.</li>
<li>Keep Trunk pristine.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2010/07/28/development-workflow/feed/</wfw:commentRss>
		<slash:comments>0</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>
	</channel>
</rss>

