<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Muffin Research Labs</title>
	
	<link>http://muffinresearch.co.uk</link>
	<description>the personal blog of Stuart Colville covering modern web development techniques and best practices</description>
	<lastBuildDate>Tue, 12 Mar 2013 20:56:45 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/muffinresearch" /><feedburner:info uri="muffinresearch" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>51.1324</geo:lat><geo:long>0.2652</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><item>
		<title>Can’t install user.js in Google Chrome</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/HIGbVI6Onsc/</link>
		<comments>http://muffinresearch.co.uk/archives/2012/10/01/cant-install-user-js-in-google-chrome/#comments</comments>
		<pubDate>Mon, 01 Oct 2012 08:36:27 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Browsers]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1267</guid>
		<description>In recent Chrome versions (22 in my case on Ubuntu) it&amp;#8217;s not possible to install user.js (Greasemonkey) scripts by just dragging them onto a window. Instead the script is downloaded and you see the following message: &amp;#8220;Extensions, apps and user scripts can only be added from the Chrome Web Store&amp;#8221; Fortunately the resolution is quite [...]</description>
				<content:encoded><![CDATA[<p>In recent Chrome versions (22 in my case on Ubuntu) it&#8217;s not possible to install user.js (Greasemonkey) scripts by just dragging them onto a window. Instead the script is downloaded and you see the following message:</p>
<p><img class="bord" src="http://mrl.staticfil.es/img/chrome-warning-user-js.png" alt="Extensions, apps and user scripts can only be added from the Chrome Web Store" /></p>
<p>&#8220;Extensions, apps and user scripts can only be added from the Chrome Web Store&#8221;</p>
<p>Fortunately the resolution is quite straight-forward. First download the script you want to a local directory/folder, then go to <a href="chrome://chrome/extensions/">chrome://chrome/extensions/</a> and drag the user.js script there instead. This feature is designed to protect users from malicious installs and as long as you know the workaround to install user.js scripts it&#8217;s not too much of a big deal.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=HIGbVI6Onsc:LWNx3M0cCjE:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=HIGbVI6Onsc:LWNx3M0cCjE:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=HIGbVI6Onsc:LWNx3M0cCjE:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=HIGbVI6Onsc:LWNx3M0cCjE:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/HIGbVI6Onsc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2012/10/01/cant-install-user-js-in-google-chrome/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2012/10/01/cant-install-user-js-in-google-chrome/</feedburner:origLink></item>
		<item>
		<title>Insert a tab character in vim when expand tabs is on</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/I47mKv48bng/</link>
		<comments>http://muffinresearch.co.uk/archives/2012/09/18/insert-a-tab-character-in-vim-when-expand-tabs-is-on/#comments</comments>
		<pubDate>Tue, 18 Sep 2012 10:00:10 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1264</guid>
		<description>I have vim set-up to use spaces in place of tabs. Sometimes you need to use an actual tab e.g. editing a Makefile. Now whilst it&amp;#8217;s possible to change settings so that tabs are used for specific files, a quick tip to remember is to simply type in insert mode: Ctrl+v tab That is Ctrl [...]</description>
				<content:encoded><![CDATA[<p>I have vim set-up to use spaces in place of tabs. Sometimes you need to use an actual tab e.g. editing a Makefile. Now whilst it&#8217;s possible to change settings so that tabs are used for specific files, a quick tip to remember is to simply type in insert mode:</p>
<p><code>Ctrl+v tab</code></p>
<p>That is Ctrl and &#8220;V&#8221; and hit the tab key, et voila you&#8217;ve entered an actual tab.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=I47mKv48bng:lkKq_ahgV3w:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=I47mKv48bng:lkKq_ahgV3w:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=I47mKv48bng:lkKq_ahgV3w:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=I47mKv48bng:lkKq_ahgV3w:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/I47mKv48bng" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2012/09/18/insert-a-tab-character-in-vim-when-expand-tabs-is-on/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2012/09/18/insert-a-tab-character-in-vim-when-expand-tabs-is-on/</feedburner:origLink></item>
		<item>
		<title>Fixing pbuilder dependency 404 errors</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/HJLItxNHRTM/</link>
		<comments>http://muffinresearch.co.uk/archives/2012/09/15/fixing-pbuilder-dependency-404-errors/#comments</comments>
		<pubDate>Sat, 15 Sep 2012 12:45:47 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Linux/Unix]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1240</guid>
		<description>If you&amp;#8217;re building packages with pbuilder sometimes you might hit something like the following errors which cause the build to fail because the dependencies can&amp;#8217;t be found. Err http://archive.ubuntu.com/ubuntu/ precise-updates/main devscripts i386 2.11.6ubuntu1.2 404 Not Found [IP: 91.189.92.188 80] Err http://archive.ubuntu.com/ubuntu/ precise-updates/main openssl i386 1.0.1-4ubuntu5.2 404 Not Found [IP: 91.189.92.188 80] The cause is the [...]</description>
				<content:encoded><![CDATA[<p>If you&#8217;re building packages with pbuilder sometimes you might hit something like the following errors which cause the build to fail because the dependencies can&#8217;t be found.</p>
<pre><code>Err http://archive.ubuntu.com/ubuntu/ precise-updates/main devscripts i386 2.11.6ubuntu1.2
  404  Not Found [IP: 91.189.92.188 80]
Err http://archive.ubuntu.com/ubuntu/ precise-updates/main openssl i386 1.0.1-4ubuntu5.2
  404  Not Found [IP: 91.189.92.188 80]</code></pre>
<p>The cause is the pbuilder image being out of date and some dep packages are no longer present becuase they&#8217;ve been superceded by more recent versions. The good news is the fix is really simple just run:</p>
<p><code>pbuilder-&lt;dist&gt; update</code></p>
<p>Which will update your pbuilder image and from there the dependency installation should work just fine.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=HJLItxNHRTM:VNn1Pehr21A:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=HJLItxNHRTM:VNn1Pehr21A:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=HJLItxNHRTM:VNn1Pehr21A:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=HJLItxNHRTM:VNn1Pehr21A:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/HJLItxNHRTM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2012/09/15/fixing-pbuilder-dependency-404-errors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2012/09/15/fixing-pbuilder-dependency-404-errors/</feedburner:origLink></item>
		<item>
		<title>GNU screen: open tab in current working directory</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/IJCPI0puzc8/</link>
		<comments>http://muffinresearch.co.uk/archives/2011/11/08/gnu-screen-open-tab-in-current-working-directory/#comments</comments>
		<pubDate>Tue, 08 Nov 2011 10:54:18 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1228</guid>
		<description>A nice trick for having screen open a new tab in the same directory as the one you&amp;#8217;re currently in. To use it add it to your .screenrc # Open new window in current dir. bind c stuff "screen -X chdir \$PWD;screen^M" bind ^c stuff "screen -X chdir \$PWD;screen^M" Hat tip: mteckert on SuperUser.com</description>
				<content:encoded><![CDATA[<p>A nice trick for having screen open a new tab in the same directory as the one you&#8217;re currently in. To use it add it to your .screenrc</p>
<p><code># Open new window in current dir.<br />
bind c stuff "screen -X chdir \$PWD;screen^M"<br />
bind ^c stuff "screen -X chdir \$PWD;screen^M"</code></p>
<p>Hat tip: <a href="http://superuser.com/users/83362/mteckert" target="_blank">mteckert</a> on <a href="http://superuser.com/questions/291907/using-screenrc-how-can-i-make-c-a-c-open-a-new-window-at-the-current-windows" target="_blank">SuperUser.com</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=IJCPI0puzc8:EQI6dr1VgIM:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=IJCPI0puzc8:EQI6dr1VgIM:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=IJCPI0puzc8:EQI6dr1VgIM:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=IJCPI0puzc8:EQI6dr1VgIM:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/IJCPI0puzc8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/11/08/gnu-screen-open-tab-in-current-working-directory/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2011/11/08/gnu-screen-open-tab-in-current-working-directory/</feedburner:origLink></item>
		<item>
		<title>Recover Files from Nandroid Backup</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/vnHVOWqe-Fs/</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>I recently flashed my Htc Desire with CyanogenMod 7.1 and I have to say it&amp;#8217;s great to be free of htc sense. Given the rigmarole around the official Gingerbread update for the Desire I don&amp;#8217;t think my next phone will be an htc one. Anyhow, prior to installing CM 7.1 I&amp;#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>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=vnHVOWqe-Fs:YEsMvhKR-Ho:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=vnHVOWqe-Fs:YEsMvhKR-Ho:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=vnHVOWqe-Fs:YEsMvhKR-Ho:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=vnHVOWqe-Fs:YEsMvhKR-Ho:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/vnHVOWqe-Fs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/10/27/recover-files-from-nandroid-backup/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2011/10/27/recover-files-from-nandroid-backup/</feedburner:origLink></item>
		<item>
		<title>Linux: Spotify Screensaver D-Bus Script update</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/UmMJhEcGasM/</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>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&amp;#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>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=UmMJhEcGasM:m0ZM3KvY0b4:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=UmMJhEcGasM:m0ZM3KvY0b4:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=UmMJhEcGasM:m0ZM3KvY0b4:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=UmMJhEcGasM:m0ZM3KvY0b4:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/UmMJhEcGasM" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2011/10/27/linux-spotify-screensaver-d-bus-script-update/</feedburner:origLink></item>
		<item>
		<title>Fronteers Conference 2011 – Day 2</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/cmn5i5HQZMo/</link>
		<comments>http://muffinresearch.co.uk/archives/2011/10/13/fronteers-conference-2011-day-2/#comments</comments>
		<pubDate>Thu, 13 Oct 2011 22:03:26 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Events]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1194</guid>
		<description>Here&amp;#8217;s an overview of day two of the Fronteers Confernence. For day one see: Fronteers Conference 2011 &amp;#8211; Day One Web Components and Model Driven Views &amp;#8211; Alex Russell Alex Russell&amp;#8217;s presentation was a really interesting look at the state of modern browsers along with the deatails on some really shiny but potentially controversial new [...]</description>
				<content:encoded><![CDATA[<p>Here&#8217;s an overview of day two of the Fronteers Confernence. For day one see: <a href="http://muffinresearch.co.uk/archives/2011/10/13/fronteers-conference-2011-day-one/">Fronteers Conference 2011 &#8211; Day One</a></p>
<h3>Web Components and Model Driven Views &#8211; <a href="http://infrequently.org/">Alex Russell</a></h3>
<p>Alex Russell&#8217;s presentation was a really interesting look at the state of modern browsers along with the deatails on some really shiny but potentially controversial new features that are currently being worked on in webkit. </p>
<p>First was a look at how the speed of new browser versions being released affects the progress of the web. With slides based <a href="http://arstechnica.com/web/news/2011/09/august-browser-stats-mobile-safari-on-top.ars">on the browser adoption graphs in this ars technica article</a>, it&#8217;s clear that Internet Explorer users tend to be much slower to upgrade their browsers. Especially with Firefox&#8217;s new release schedule both Chrome and Firefox are seeing much faster uptake of new versions. Faster releases means browsers are beginning to evolve more quickly resulting in a faster rate of progress. All of which can only be good for the web.</p>
<p>Moving beyond this Alex took a look at aspect of web components. First up was scoped CSS, the idea here being that you can &#8220;scope&#8221; CSS to a specific element. In this way that CSS will only apply to the children of that element.</p>
<p>Next was a look at Web Components. The first part of this is API that allows you to extend the DOM and create your own custom elements. The example given was the creation of a Comment object. Next a feature called DOM Shadow allows you to &#8220;hide&#8221; or make private the subtree that your custom object is created from so that it&#8217;s invisible to anything else. Interestingly, this is already something used in the development of video controls in webkit. This allows you to make something with divs and spans but hide the implementation details from the world. Depending on your point of view this is either fantastic news or will leave you feeling a little bit icky.</p>
<p>Lastly was a look at templating and model driven views which really do look good. It allows a template to be bound to data in such a way that when the data changes the template is updated. Definitely looks to be useful. </p>
<p>To see the full set of slides head over to <a href="http://infrequently.org/11/fronteers/fronteers.html">http://infrequently.org/11/fronteers/fronteers.html</a></p>
<h3>The New Developer Workflow &#8211; <a href="http://nimbupani.com/">Divya Manian</a></h3>
<p>This presentation was a walkthrough of steps that make-up the work flow of a modern web developer from using Version Control to deciding what browser features to use and when to use polyfills or not, vendor prefixes, CSS preprocessors and build scripts. </p>
<p>I enjoyed the walk-through of the features and capabilities of Compass (a CSS preprocessor). From a personal stand-point I&#8217;ve ever used SASS or LESS but seeing some of the features that Divya talked about I can see some worthwhile use-cases (time to try it out on a personal project maybe <img src='http://muffinresearch.co.uk/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ).</p>
<p><a href="http://nimbu.in/fronteers/">The New Developer Workflow Slides</a></p>
<h3>HTML5 Forms &#8211; KISS time &#8211; Robert Nyman</h3>
<p>Robert&#8217;s presentation was an honest look at the features of HTML5 forms and provided really good practical information on where the issues are and where as a developer you need to be careful. </p>
<p>Of particular interest was a number of caveats around using form validation features. For example: Required attribute will pass if you just submit a space. Email validation can&#8217;t cope with international characters e.g: röbert@kissonline.com won&#8217;t work. Pattern attributes can be submitted if they are empty (This is counter-intuitive though a commenter at the end of the session pointed out it makes sense that you would to use the required attr as well).</p>
<p>Overall the key takeaway here was the new HTML5 form features are cool, but like everything else they need to be used with care.</p>
<div style="width:425px" id="__ss_9583687"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/robnyman/html5-forms-kiss-time-fronteers" title="HTML5 Forms - KISS time - Fronteers" target="_blank">HTML5 Forms &#8211; KISS time &#8211; Fronteers</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/9583687" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/robnyman" target="_blank">Robert Nyman</a> </div>
</p></div>
<h3>CreativeJS &#8211; beauty in the browser &#8211; Seb Lee-Delisle</h3>
<p>This was perhaps the most surprising presentation of the event. Seb has a fantastic speaking style, very down to earth and good humoured. His presentation was in two parts, first was looking at how to create beautiful particle effects using JavaScript. Seb showed some very simple code which produced fantastic results. The approach was to create effects such as smoke and roman-candle like firework effects by approximating the physics and making it look just about right rather than spending a lot longer nailing an effect based on a 100% accurate physics model.</p>
<p>To play with all of this the files are on github. <a href="https://github.com/sebleedelisle/JavaScript-PixelPounding-demos">https://github.com/sebleedelisle/JavaScript-PixelPounding-demos</a></p>
<p>The next part was Seb&#8217;s software which turned the audiences mobiles into a giant display. This was mind-blowingly creative and a fascinating demonstration. The problems involved in this are pretty big, first was that of synchronising the signals sent to the phones so they would display in sync. This was done by measuring the delay from sending data to each phone. The next, even bigger problem was that of identifying where in the audience a given phone was. My understanding is that the software sends a pattern to each phone which it then looks for in the camera pointing at the audience. Having identified the location the audiences phones could then be used like a big display. Very cool stuff indeed!</p>
<h3>jQuery and the Open Source Process &#8211; <a href="http://ejohn.org/">John Resig</a></h3>
<p>John Resig talked in detail about how JQuery became popular through being very responsive to users in the early days and through building and fostering a community by being open and transparent.</p>
<div style="width:425px" id="__ss_8684698"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/openjournalism/open-source-process-jquery-by-john-resig" title="Open Source Process: jQuery by John Resig" target="_blank">Open Source Process: jQuery by John Resig</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/8684698" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/openjournalism" target="_blank">Open Journalism on the Open Web</a> </div>
</p></div>
<h3>In your @font-face &#8211; <a href="https://twitter.com/#!/jaffathecake">Jake Archibald</a></h3>
<p>Jake&#8217;s talk was very good &#8211; highly entertaining and also packed with interesting details about the potential issues and pitfalls in using web-fonts today. </p>
<p>There&#8217;s a number of problems to solve from how browsers treat @font-face, how to reduce the weight of fonts to download by reducing the glyphs used, to the way in which browser actually download the fonts to use them. All in all it&#8217;s a royal mess. Lastly Jake looked at how the way browser download fonts affects the final rendering.</p>
<p>Bottom line was that it really shouldn&#8217;t be this hard. </p>
<p>Jakes slides can be found at <a href="http://speakerdeck.com/u/jaffathecake/p/in-your-font-face">http://speakerdeck.com/u/jaffathecake/p/in-your-font-face</a></p>
<h3>The Prestige of being a web developer &#8211; <a href="http://www.wait-till-i.com/">Christian Heilmann</a></h3>
<p>Christian&#8217;s closing presentation was built around a theme of the film &#8220;<a href="http://www.imdb.com/title/tt0482571/">the Prestige</a>&#8220;. Christian made lots of good points about how we can be better developers by being inventive, learning from others, contributing to projects through documentation or submitting bugs and being open about what we do.</p>
<p><a href="http://www.wait-till-i.com/2011/10/07/the-prestige-of-being-a-web-developer-fronteers-11/">Slides and audio with a transcript are available on Christian&#8217;s blog</a> </p>
<p>And that was it.</p>
<p>A big thank-you to the speakers and organisers for putting on an excellent conference.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=cmn5i5HQZMo:_MHb0P2CylM:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=cmn5i5HQZMo:_MHb0P2CylM:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=cmn5i5HQZMo:_MHb0P2CylM:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=cmn5i5HQZMo:_MHb0P2CylM:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/cmn5i5HQZMo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/10/13/fronteers-conference-2011-day-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2011/10/13/fronteers-conference-2011-day-2/</feedburner:origLink></item>
		<item>
		<title>Fronteers Conference 2011 – Day One</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/YaN3HnGyXAU/</link>
		<comments>http://muffinresearch.co.uk/archives/2011/10/13/fronteers-conference-2011-day-one/#comments</comments>
		<pubDate>Thu, 13 Oct 2011 17:04:49 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Events]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1177</guid>
		<description>Recently I attended Fronteers 2011 held in Amsterdam. The entire conference was very well organised and the content across the two days was nicely balanced between more general thought provoking presentations, practical things that you could take away and use today and talks on where the web is heading, with good detail on some of [...]</description>
				<content:encoded><![CDATA[<p>Recently I attended <a href="http://fronteers.nl/congres/2011">Fronteers 2011</a> held in Amsterdam. The entire conference was very well organised and the content across the two days was nicely balanced between more general thought provoking presentations, practical things that you could take away and use today and talks on where the web is heading, with good detail on some of the new things we will have to play with in the future.</p>
<p>Here&#8217;s an overview of Day One. </p>
<h3>The Future is Native &#8211; <a href="http://aralbalkan.com/">Aral Balkan</a></h3>
<p>Aral Balkan presented the opening keynote with a presentation looking at where web experiences sit in relation to experiences provided by native applications. In a nutshell this presentation was about inspiring developers to embrace Use Experience (UX), to focus on the user&#8217;s needs rather than focus on technical considerations at the beginning. </p>
<p>Aral advocated a notion of &#8220;Write once, optimise everywhere&#8221;, starting with progressive enhancement as a basis, then optimising for features, and then to optimise for specific devices. I personally feel this is good ideal to aim for, however my immediate thought was that it&#8217;s important to be pragmatic and choose the battles to fight in terms of what devices you optimise for. </p>
<p>Towards the end of Aral&#8217;s presentation he looked at how UX is difficult; as you move away from face to face communication towards using a device you&#8217;re losing visual and audible cues. This means getting things right can be difficult but the right UX provides the &#8220;Superman effect&#8221; which in other words is to make the user feel empowered and feel good about their interactions with an application.</p>
<h3>Accessibility for the Modern Web &#8211; <a href="http://boxofchocolates.ca/">Derek Featherstone</a></h3>
<p>Derek Featherstone, gave a great talk on what considerations there are around building web applications that take into account accessibility. Firstly he looked at work he&#8217;d done in the past that had been criticised as being a collection of hacks. These were scripts that added accessibility features to existing applications, for example: <a href="http://simplyaccessible.com/article/keyboard-accessible-youtube-controls/">keyboard accessible you tube controls</a>, and adding keyboard accessible controls to <a href="http://ironfeathers.ca/routes/29/">google maps</a>. Derek went on to explain that the need for such &#8220;hacks&#8221; is because of decisions someone else made.</p>
<p>Following on from these inital examples Derek walked through a number of real-world examples where odd markup decisions had been made to provide (in come cases) a certain look and feel rather than using the best-fit native elements. For example Amazon use a convoluted customized checkbox widget rather than use a checkbox. Another example was Gmail&#8217;s compose links being a span with an onclick rather than a link. </p>
<p>Looking at examples of real-world problems the key points made were around choosing the right control for the job. Buttons for actions link to take the user somewhere. If you&#8217;re needing to use tabindex=0 to make something focusable then this a good point to reconsidering if you&#8217;re using the right control. </p>
<p>Another issue considered was management of focus. If a link opens a dialogue then once the user has closed the dialogue the focus should go back to the link that opened the dialogue. For a keyboard user focus is crucial and if you send focus to the top of the page constantly then you&#8217;re providing a very poor user experience. </p>
<p>Derek also provided some examples of use of tabindex had resulted in &#8220;keyboard trap&#8221;, in this case it was a form that had focus controlled in such a way that you couldn&#8217;t get to to certain fields through the use of tabbing to move through the fields. </p>
<p>Looking at keyboard interactivity Derek pointed out the caveats of using role=button on links. As assistive technology that support aria roles announces a link with role=button as a button the user will expect to be able to use the spacebar to activate it. However unless the site author has added keyboard handling to allow for this spacebar will do nothing. This is something that&#8217;s all too easy to do and whilst trying to be well-meaning the addition of such a role has impaired accessibility. </p>
<p>Derek&#8217;s presentation provided lots of great examples and practical advice and it&#8217;s definitely made me want to dive in to everything that we&#8217;re building an re-evaluate what improvements we can make to provide a better experience for all our users. In addition I feel it&#8217;s important to get a good sense for what a baseline experience should be so that it becomes a given that we build accessibility into sites rather than facing the prospect of retro-fitting it afterwards, as that&#8217;s always going to be more expensive in terms of time and effort.</p>
<h3>CSS3 Secrets: Ten things you might not know about CSS3 &#8211; <a href="http://leaverou.me/">Lea Verou</a></h3>
<p>Lea provided a great showcase of cool tips and tricks you can achieve with CSS3. Lots of interesting and cool stuff here. I particularly like the gradient tricks for faux-columns and the background-origin tips. Interestingly this highlights something I love about working with CSS in that creative approaches to problems can yield really good results. One of the best examples of this was the use of nth-child selectors to provide layout control based on the number of elements. </p>
<div style="width:425px" id="__ss_9591089"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/LeaVerou/css3-secrets-10-things-you-might-not-know-about-css3" title="CSS3 secrets: 10 things you might not know about CSS3" target="_blank">CSS3 secrets: 10 things you might not know about CSS3</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/9591089" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/LeaVerou" target="_blank">Lea Verou</a> </div>
</p></div>
<h3>You too can be a bedwetting antf**ker: <a href="http://www.brucelawson.co.uk/">Bruce Lawson</a></h3>
<p>Bruce&#8217;s Presentation highly entertaining presentation walked us through the new elements in HTML5, noting problems that currently existing in the specifications. This was a good overview of what&#8217;s new in HTML5 and where new elements provide more options for describing your content with more appropriate semantics.</p>
<div style="width:425px" id="__ss_9588237"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/brucelawson/you-too-can-be-a-bedwetting-antfucker-bruce-lawson-opera-fronteers-2011" title="You too can be a bedwetting antfucker: Bruce Lawson, Opera, Fronteers 2011" target="_blank">You too can be a bedwetting antfucker: Bruce Lawson, Opera, Fronteers 2011</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/9588237" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/brucelawson" target="_blank">brucelawson</a> </div>
</p></div>
<h3>Go with the flow: <a href="http://www.the-haystack.com/">Stephen Hay</a></h3>
<p>Stephen gave a talk on the exciting features of CSS Regions. <a href="http://caniuse.com/css-regions">CSS regions are just appearing on the horizon in terms of current browser support</a>, but that doesn&#8217;t diminish what interest creative possibilities they open up. I&#8217;d definitely recommend checking out the deck.</p>
<div style="width:425px" id="__ss_9595283"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/stephenhay/go-with-the-flow-9595283" title="Go With The Flow" target="_blank">Go With The Flow</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/9595283" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/stephenhay" target="_blank">Stephen Hay</a> </div>
</p></div>
<h3>The future of CSS&mdash;Current Experiments and Near Future Reality &#8211; <a href="http://www.xanthir.com/blog/">Tab Atkins Jr</a></h3>
<p>In this presentation Tab Atkins Jr (who works for google as a CSS specification writer) outlined a lot of cool features that are coming into CSS specifications and in some cases these are things that are starting to be implemented albeit experimentally in most cases.</p>
<h4>Image function</h4>
<pre><code>background: image("foo.webp", "foo.svg", "foo.png", blue);
background: image(rgba(0,0,255,.2)), url(foo.jpg);</code></pre>
<p>This allows fall-backs in the first example the first item that loads is used.<br />
The second example allows a transparent colour to be overlaid an image.</p>
<h4>Flexbox</h4>
<p>I particularly liked the flexbox example which demonstrated an input and button with the flex() used for the width so that it takes up the remaining space up to the button.</p>
<pre><code>&lt;div style="display: flexbox;"&gt;
	&lt;input style="width: flex(); display: block;"&gt;
	&lt;button&gt;foo&lt;/button&gt;
&lt;/div&gt;</code></pre>
<h4>Calc</h4>
<p>The <code>calc()</code> function (I can see this coming in very handy):</p>
<pre><code>calc(50% + 20px)
calc(100% / 7)</code></pre>
<p><code>attr()</code> lets you pull values from attributes on the element.</p>
<pre><code>width: attr(data-size as px, 100px);</code></pre>
<h4>CSS vars!!!</h4>
<pre><code>@var $header-color #006;
@var $main-color #06c;
@var $secondary-color #c06;
a { color: $main-color; }
a:visited { color: $secondary-color; }
h1 { 
  color: $header-color;
  background: linear-gradient(left,$main-color, transparent 25%);
}</code></pre>
<p>Tab noted that a lot of innovation was happening in the CSS preprocessor space and this was being recognised and informing some of the newer specs.</p>
<p>To see the full range of examples Tab&#8217;s Slides can be seen here: <a href="http://www.xanthir.com/talks/2011-10-06/">http://www.xanthir.com/talks/2011-10-06/</a></p>
<h3>Passion. Purpose. Promise. Pursuit &#8211; <a href="http://www.jenseninman.com/">Leslie Jensen-Inman</a></h3>
<p>The final presentation of day one was a call to action to embrace the things we are passionate about, define our purpose, make commitments to ourselves and others (promise) and to pursue these goals to make greats things and do good.</p>
<p>This was a sound message, and it&#8217;s easy to see how it can apply to being a web developer. Also something that we don&#8217;t often do is step back and evaluate ourselves and look at where we are heading and rationalise our interests with what we want to achieve.</p>
<p><a href="http://speakerdeck.com/u/jenseninman/p/passion-purpose-promise-pursuit ">Passion. Purpose. Promise. Pursuit. slide deck on Speaker Deck</a></p>
<p>For Day two see: <a href="http://muffinresearch.co.uk/archives/2011/10/13/fronteers-conference-2011-day-2/">Fronteers Conference Day 2</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=YaN3HnGyXAU:J-S48R8wr-I:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=YaN3HnGyXAU:J-S48R8wr-I:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=YaN3HnGyXAU:J-S48R8wr-I:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=YaN3HnGyXAU:J-S48R8wr-I:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/YaN3HnGyXAU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/10/13/fronteers-conference-2011-day-one/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2011/10/13/fronteers-conference-2011-day-one/</feedburner:origLink></item>
		<item>
		<title>Ubuntu: add-apt-repository: command not found</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/7gnq65MWePw/</link>
		<comments>http://muffinresearch.co.uk/archives/2011/08/31/ubuntu-add-apt-repository-command-not-found/#comments</comments>
		<pubDate>Wed, 31 Aug 2011 01:10:37 +0000</pubDate>
		<dc:creator>Stuart Colville</dc:creator>
				<category><![CDATA[Snippets]]></category>

		<guid isPermaLink="false">http://muffinresearch.co.uk/?p=1174</guid>
		<description>When you&amp;#8217;re using a minimal Ubuntu install if you find the &amp;#8216;add-apt-repository&amp;#8217; command is missing (it&amp;#8217;s useful for adding PPAs and other repositories), then simply run: sudo apt-get install python-software-properties</description>
				<content:encoded><![CDATA[<p>When you&#8217;re using a minimal Ubuntu install if you find the &#8216;add-apt-repository&#8217; command is missing (it&#8217;s useful for adding PPAs and other repositories), then simply run: </p>
<p><code>sudo apt-get install python-software-properties</code></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=7gnq65MWePw:pCu_WeVVgDo:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=7gnq65MWePw:pCu_WeVVgDo:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=7gnq65MWePw:pCu_WeVVgDo:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=7gnq65MWePw:pCu_WeVVgDo:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/7gnq65MWePw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://muffinresearch.co.uk/archives/2011/08/31/ubuntu-add-apt-repository-command-not-found/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2011/08/31/ubuntu-add-apt-repository-command-not-found/</feedburner:origLink></item>
		<item>
		<title>Linux: Spotify Track Notifier with added D-Bus love</title>
		<link>http://feedproxy.google.com/~r/muffinresearch/~3/-E6fNXMOHzo/</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>I&amp;#8217;ve recently updated the spotify notifier example I&amp;#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&amp;#8217;t visible in D-feet which had led to the erroneous assumption it wasn&amp;#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>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/muffinresearch?a=-E6fNXMOHzo:WjEyLLF5hds:Y9O6f-ipdLU"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=Y9O6f-ipdLU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=-E6fNXMOHzo:WjEyLLF5hds:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=-E6fNXMOHzo:WjEyLLF5hds:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/muffinresearch?a=-E6fNXMOHzo:WjEyLLF5hds:2nqncYFp4_M"><img src="http://feeds.feedburner.com/~ff/muffinresearch?d=2nqncYFp4_M" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/muffinresearch/~4/-E6fNXMOHzo" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://muffinresearch.co.uk/archives/2011/03/23/linux-spotify-track-notifier-with-added-d-bus-love/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 0.358 seconds --><!-- Cached page served by WP-Cache -->
