<?xml version="1.0" encoding="UTF-8"?><rss version="2.0>
	<channel>
		<title>Aching Brain</title>
		<link>http://achingbrain.net</link>
		<description>A blog about technology</description>
		<lastBuildDate>Wed, 23 May 2012 09:18:14 +0100</lastBuildDate>
		<language>en</language>
 
		<item>
			<title><![CDATA[Facebook IPO]]></title>
			<link>http://achingbrain.net/facebook-ipo</link>
			<guid>http://achingbrain.net/facebook-ipo</guid>
			<pubDate>Tue, 22 May 2012 08:23:55 +0100</pubDate>
			<description><![CDATA[<p>So after three days of trading, Facebook shares have <a href="http://www.latimes.com/business/la-fi-0523-facebook-regrets-2-20120523,0,2596022.story">lost 26% in value</a>.</p>

<p>I like to think they'll bounce back for the sake of pending tech IPOs everywhere, but I just don't understand the hype.</p>

<p>Fundamentally my skepticism boils down to the fact that at the end of 2011 they reported <a href="http://www.sec.gov/Archives/edgar/data/1326801/000119312512034517/d287954ds1.htm#toc287954_8">post tax profits of $1b on revenues of $3.7b</a>, which is a lot, however they had <a href="http://newsroom.fb.com/content/default.aspx?NewsAreaId=20">845m users</a>, giving a per-user profit of $1.18 from $4.38.</p>

<p>A little over a dollar per user, per year.  Yet, when their IPO launched they were valued more than Amazon.  Think about that for a moment - if you are anything like me you do a lot of shopping on Amazon.  Sure, they don't have <a href="http://newsroom.fb.com/content/default.aspx?NewsAreaId=22">901m users at the time of writing</a> but I'd be amazed if they weren't making a substantial amount more than $1 per year out of each of us.</p>

<p>Since they admit that <a href="http://www.sec.gov/Archives/edgar/data/1326801/000119312512034517/d287954ds1.htm#toc287954_2">they generate a substantial majority of their revenue from advertising</a>, Facebook's challenge is going to be making the site more attractive to advertisers in order to raise that per user per year amount.  This will inevitably come at the expense of the user experience - either more adverts, "promoted" stories or those creepy targeted ads.  Too much and the users will jump ship for whatever hot thing comes sailing along next which must be a massive concern for Facebook as their profitability is intrinsically linked to their having an incredibly large user base.</p>

<p>Considering all this, seeing the initial investor rush reminded me a little of the '<a href="http://youtu.be/nEgKXNx2NMs?t=7m51s">Is something brilliant happening?</a>' bit of the final episode of Nathan Barley.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Working From Home]]></title>
			<link>http://achingbrain.net/working-from-home</link>
			<guid>http://achingbrain.net/working-from-home</guid>
			<pubDate>Sun, 20 May 2012 20:23:55 +0100</pubDate>
			<description><![CDATA[<iframe width="100%" height="315" src="http://www.youtube.com/embed/EL_g0tyaIeE" frameborder="0" allowfullscreen></iframe>

<p>The thing that surprised me about this, I suppose, is that Pixar allow people to take copies of their work-in-progress movies home.  I would have thought they'd be incredibly paranoid and lock everything down as much as possible to prevent leaks.</p>

<p>Then again, they didn't exactly say that the machine Galyn had at home wasn't locked down - they had to take it into the office to extract the data instead of just making a copy and taking that in.</p>

<p>Storage issues aside, imagine if they'd had distributed version control...</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Commodity Apples]]></title>
			<link>http://achingbrain.net/commodity-apples</link>
			<guid>http://achingbrain.net/commodity-apples</guid>
			<pubDate>Thu, 19 Apr 2012 20:23:55 +0100</pubDate>
			<description><![CDATA[<p>John Moltz <a href="http://verynicewebsite.net/2012/04/the-argument-that-apple-cannot-keep-growing/">says</a>:</p>

<blockquote>
  <p>It seems to me that there is a group of people who believe that all markets eventually commoditize and everyone will be satisfied with sub-standard products as long as the prices are lower. Not coincidentally, these people also tend to write sub-standard analysis of Apple.</p>
</blockquote>

<p>Commoditisation will occur when enough of your competitors figure out how to produce something as good as what you have for less than you can.  Apple's trick is consistently being a step or three ahead of the market - this is how they avoid commoditisation.</p>

<p>The Power Mac, the iBook, TiBook &amp; MacBook Air, the iPod, iPhone &amp; iPad - each one defined or radically altered how the hardware of it's class should look and how software should interact with it.  You can see their influence in how the products of competitors resemble them a year or so after their introduction (although usually with some significant flaws).</p>

<p>If, like Apple, you can consistently innovate, then by the time your products become commoditised, you've already moved on to the next big thing so it doesn't affect you.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Uniqueness]]></title>
			<link>http://achingbrain.net/uniqueness</link>
			<guid>http://achingbrain.net/uniqueness</guid>
			<pubDate>Wed, 23 Jun 2010 15:56:04 +0100</pubDate>
			<description><![CDATA[<p>Something we've been ruminating on at work recently is uniqueness. We'd quite like everything in our system to have a unique identifier, usually referred to as a GUID or Globally Unique IDentifier. This way you can access any entity from any place, and the display method of said entity is determined by the place of access. By way of example, if you were to access an email, you'd see the email, but if you were looking at a folder full of emails, you'd see the email in the context of the folder that contains it.</p>

<p>Back to uniqueness though. We don't really need our GUIDs to be truly globally unique, only unique within our system. Ideally we'd also like them to be short so if you email someone a url their client won't wrap the line in the middle of our GUID.</p>

<p>The simplest way to ensure this would be with a number. This is easy to maintain as they can be sequential, generated by a database and don't need any special rules. The only problem is the namespace is not very big. If you allow five characters for your GUID in the familiar base 10 number system, you have 10,000 potential values, or 10<sup>5</sup>.</p>

<p>10,000 is a good start but what if you've got entities in different tables? Entity#1 in table A is not the same as entity#1 in table B. Perhaps we can do better.</p>

<p>The canonical GUID implementation is the <a href="http://en.wikipedia.org/wiki/Universally_Unique_Identifier">Universally Unique Identifier</a> or UUID. UUID has been standardised as <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC4122</a> by people a lot cleverer than me so let's assume it's pretty good. A UUID takes the following form:</p>

<p>550e8400-e29b-41d4-a716-446655440000</p>

<p>Right away we can see that it's going to result in a much larger namespace than using numbers as it incorporates letters as well. This expands the value each character can be from 10 to (26 + 10), giving us a base 36 namespace. A five character GUID in base 36 has 60,466,176 possible values, or 36<sup>5</sup>.</p>

<p>Version 5 UUIDs are calculated by taking an existing source of uniqueness (a URL is recommended) and hashing it using the SHA-1 algorithm. This is not fantastic for us as we're trying to create a GUID which will be used in the creation of a URL, so we're going to have to look elsewhere.</p>

<p>The simple thing to do would be to generate them randomly. This is not as bad as it sounds and appears to be a <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/UUID.html#randomUUID()">standard</a> way of doing it. We've just introduced a subtle problem though. As we are now randomly generating the GUID we become vulnerable to the <a href="http://en.wikipedia.org/wiki/Birthday_problem">birthday paradox</a>. From this <a href="http://my.instacalc.com/calc/91ca9ae67a434f82be1b84d85ea9e065">rather nifty calculator</a>, we can deduce that we'll reach a 99.9% probability of a collision (eg. two items with the same GUID) with a five character GUID in base 36 after 29,903 items. Although this means we are fairly likely to have collisions with randomly generated GUIDs, it's still much better than using integers which reach 99.9% after just 372 items.</p>

<p>Clearly the way to increase the namespace is to increase the base of the number system we are using. There's easy thing we can do here - include capital and lower case letters. YouTube do this to great effect, even including punctuation:</p>

<p><a href="http://www.youtube.com/watch?v=ZOU8GIRUd_g">http://www.youtube.com/watch?v=ZOU8GIRUd_g</a></p>

<p>So lower case (26), upper case (26), integers (10) and underscores (1) gives us base 56 - 550,731,776 potential values at five characters, or 56<sup>5</sup>.  No need to stop at underscores though - <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC2396</a> tells us that the only restricted characters for URLs are ; / ? : @ &amp; = + $ ,. That leaves !@£%^*()[]{}"'\|&gt;&lt;. etc etc.</p>

<p>At 11 base 56 characters, YouTube can accommodate nearly 17,000,000,000,000,000,000 videos (or 1.7 x 10<sup>-8</sup> <a href="http://www.facebook.com/pages/The-Official-Petition-to-Establish-Hella-as-the-SI-Prefix-for-1027/277479937276?v=info">hella</a> videos) before running out of GUIDs. When they do, they can just add another character on to literally increase the namespace exponentially or simply allow additional punctuation marks. Taking the birthday paradox into account, they can have 15,325,262,787 videos before a 99.9% probability of collision occurs. If <a href="http://wiki.answers.com/Q/How_many_videos_are_there_on_YouTube">they currently have 120,000,000</a> they are still a long way off needing to extend their namespace.</p>

<p>So there you have it. Increase your number base to reduce the chance of GUID collision and make your life easy when trying to make everything in your database have a unique, email friendly identifier.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[The Register's guide to Linux Distributions]]></title>
			<link>http://achingbrain.net/the-registers-guide-to-linux-distributions</link>
			<guid>http://achingbrain.net/the-registers-guide-to-linux-distributions</guid>
			<pubDate>Mon, 21 Jun 2010 19:06:13 +0100</pubDate>
			<description><![CDATA[<blockquote>Tomorrow, we'll tell you how to get them, burn them and set them up to dual-boot with Windows and on Wednesday there will be a guide to tweaking your new setup and getting it ready for use.</blockquote>

<p>Three days to set up and have a Linux desktop ready to use.  Yep, that about tallies with my memory of it.</p>

<p><a href="http://www.theregister.co.uk/2010/06/21/reg_linux_guide_1">http://www.theregister.co.uk/2010/06/21/reg<em>linux</em>guide_1</a></p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Security Hacking for kids]]></title>
			<link>http://achingbrain.net/security-hacking-for-kids</link>
			<guid>http://achingbrain.net/security-hacking-for-kids</guid>
			<pubDate>Thu, 13 Aug 2009 16:45:54 +0100</pubDate>
			<description><![CDATA[<p>From <a href="http://www.wired.com/geekdad/2009/08/5-hacks-you-can-explore-with-your-kids/">Five hacks you can explore with your kids</a> (Wired)
<blockquote>The thrill of getting a root shell using a well crafted buffer overflow is a joy few non-geeks will ever know. Security cracking is skill that requires an in depth knowledge of networking, operating systems and programming. Helping your kids build these important skills without turning into web site trashing script kiddies is every good parents job.</blockquote>
Well quite.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Updates]]></title>
			<link>http://achingbrain.net/updates</link>
			<guid>http://achingbrain.net/updates</guid>
			<pubDate>Sun, 02 Aug 2009 11:20:14 +0100</pubDate>
			<description><![CDATA[<p>I'd forgotten what a time consuming, involving and generally ill thought through process updating a copy of Windows is.  On the Mac you use a desktop application, on Windows a flaky looking web app.  On the Mac you select things like "QuickTime Update 7.6.2" which kind of makes sense, on Windows you select "Critical Update for Windows XP (KB9832082)" which might as well be in Esperanto.</p>

<p>Operating system updates on the Mac are all rolled together, so if you are on 10.5.3, updating to 10.5.7 is one step (and a big download).  On Windows you need to repeatedly visit Windows Update to ensure that no new updates have been unlocked by installing the last set.</p>

<p>After selecting your desired updates, on the Mac any further interaction is done right at the start of the process - EULA clicking, etc.  On Windows the process is constantly interrupted with wizard after wizard after wizard, meaning that you can't just click "go", put the kettle on and come back half an hour later.  No, you have to constantly hand hold the process like some it's some sort of attention seeking toddler.</p>

<p>It also offered me the option of installing something called Microsoft Genuine Windows Notifications which promised, if my copy of windows was not "Genuine", to constantly bombard me with nagging reminders to "solve" this problem.</p>

<p>Who in their right mind would actually choose to install such a piece of software?  If your copy is legit you don't need it and if it's not, you don't want it.</p>

<p>It then prompted me to follow a link to a list of benefits of using "Genuine" Windows software.  I didn't follow the link, but presumably it's just a picture of Steve Balmer in a bath of money.</p>

<p>Sorry that this post is so unashamedly pro Mac.  I'd have mentioned the Linux update process as these days it's pretty painless.  The update process itself is painless, I mean.  The pain comes after the update when you find that half of your shit doesn't work any more.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Flashpaper]]></title>
			<link>http://achingbrain.net/flashpaper</link>
			<guid>http://achingbrain.net/flashpaper</guid>
			<pubDate>Sat, 06 Sep 2008 08:09:47 +0100</pubDate>
			<description><![CDATA[<p>Adobe have <a href="http://uk.techcrunch.com/2008/09/04/startups-in-chaos-as-adobes-flashpaper-discontinues/">despatched</a> Flashpaper to the same grave of irrelevant products as FreeHand and ImageReady.  Considering Flashpaper was made by Macromedia before their assimilation, it was kind of on the cards due to it's competition with PDF.</p>

<p>From the article the CEO a doomed startup whines:
<blockquote>What about all the websites that have been storing all their documents with Flashpaper? It will be a major job having to transfer all those documents to a new solution</blockquote>
Perhaps if instead of willingly submitting to vendor lock in they stored their documents in a <a href="http://www.w3.org/TR/xhtml1/">recognised, open standard that's widely implemented by multiple vendors</a> they would not have this problem.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[FlashCommand]]></title>
			<link>http://achingbrain.net/flashcommand</link>
			<guid>http://achingbrain.net/flashcommand</guid>
			<pubDate>Mon, 01 Sep 2008 08:45:55 +0100</pubDate>
			<description><![CDATA[<p>I found this <a href="http://code.google.com/p/flashcommand/">excellent command line tool</a> to compile Flash movies the other day.</p>

<p>It works like this:</p>

<pre lang="bash">flashcommand -p -s /path/to/fla</pre>

<p>The -p switch means 'publish' and '-s' specifies the path to the source .fla file.  It works by opening Flash CS3 in the background and instructing it to compile the movie, consequently it will respect the publish settings you've defined in the .fla so the generated .swf file will end up in the right directory.</p>

<p>Combining this with Flash CS3's ability to import an external AS3 file to use with each movie means bar the initial .fla file creation you'll never have to use Adobe's painfully bad authoring environment ever again.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[UK communications database]]></title>
			<link>http://achingbrain.net/uk-communications-database</link>
			<guid>http://achingbrain.net/uk-communications-database</guid>
			<pubDate>Tue, 20 May 2008 16:24:46 +0100</pubDate>
			<description><![CDATA[<p>The latest krazee plan from the Home Office's policy department seems to be a massive database containing the details of <a href="http://news.bbc.co.uk/1/hi/technology/7410885.stm">every phone conversation and email sent</a> in the UK.</p>

<p>Assuming it works (it won't) then at least they'll realise just how bad the spam situation is.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Running FMS 3 on Gentoo Linux]]></title>
			<link>http://achingbrain.net/running-fms-3-on-gentoo-linux</link>
			<guid>http://achingbrain.net/running-fms-3-on-gentoo-linux</guid>
			<pubDate>Thu, 24 Apr 2008 13:22:47 +0100</pubDate>
			<description><![CDATA[<p>I've been trying to install <span style="text-decoration: line-through;">Macromedia</span> Adobe Flash Media Server 3 on my local development box and have run into some problems.</p>

<p>To help out anyone else trying to do the same thing, here's how I did it.</p>

<p>First you need to install nspr</p>

<pre lang="bash">
emerge -uDv dev-libs/nspr
</pre>

<p>Add a user/group for it to run under:</p>

<pre lang="bash">
groupadd fms
useradd -g fms -d /dev/null -s /bin/bash fms
</pre>

<p>Then download and extract the media server as per usual.  Before installing it, you need to fiddle the install script so that it will install on your "unsupported" platform.  Open installFMS in your favourite text editor and find the line that reads</p>

<pre lang="bash">
DISTRO=`check_distro`
</pre>

<p>Change it to something appropriate like</p>

<pre lang="bash">
DISTRO=redhat-RHEL4-i686
</pre>

<p>Then start the installation script as normal.  Tell it that you don't want it to run as a daemon (as it requires the Red Hat only chkconfig command) and that you don't want it to start the server when done.</p>

<p>After you've installed the server, you'll need to make the bundled <code>libasneu.so.1</code> library available for use:</p>

<pre lang="bash">
ln -s /opt/fms/libasneu.so.1 /lib/libasneu.so.1
</pre>

<p>For some reason the install messed up the configuration files, adding things like the administrative user name twice.  Check conf/fms.ini to make sure this hasn't happened to you.</p>

<p>The installer creates init scripts at <code>/etc/init.d</code> but in order to use them you first need to create a file called <code>.autostart</code> in the installation directory:</p>

<pre lang="bash">
touch .autostart
</pre>

<p>You should then be able to start and stop the server normally:</p>

<pre lang="bash">
/etc/init.d/fms start
/etc/init.d/fms stop
</pre>

<p>And use <code>rc-update</code> to have the server start on boot:</p>

<pre lang="bash">
rc-update add fms default
</pre>

<p>Good luck.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Vista SP1 sales video]]></title>
			<link>http://achingbrain.net/vista-sp1-sales-video</link>
			<guid>http://achingbrain.net/vista-sp1-sales-video</guid>
			<pubDate>Thu, 17 Apr 2008 15:45:50 +0100</pubDate>
			<description><![CDATA[<p>I really hope this is a spoof as it makes me want to stab myself in the eye with a fork.</p>

<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="wmode" value="transparent" /><param name="src" value="http://www.youtube.com/v/sPv8PPl7ANU&amp;hl=en" /><embed type="application/x-shockwave-flash" width="425" height="355" src="http://www.youtube.com/v/sPv8PPl7ANU&amp;hl=en" wmode="transparent"></embed></object></p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Prototype String.toQueryParams() weirdness]]></title>
			<link>http://achingbrain.net/prototype-stringtoqueryparams-weirdness</link>
			<guid>http://achingbrain.net/prototype-stringtoqueryparams-weirdness</guid>
			<pubDate>Tue, 15 Apr 2008 14:34:46 +0100</pubDate>
			<description><![CDATA[<p>I just came across this while using <a href="http://www.prototypejs.org">Prototype</a>:</p>

<pre class="prettyprint linenums">
"section=blo%g&id=45".toQueryParams();
</pre>

<p>To save you the trouble of running it yourself, I'll tell you what happens - the unescaped percent symbol causes a URI malformed error to be thrown.</p>

<p>Very odd.  The Prototype documentation for <a href="http://www.prototypejs.org/api/string#method-toqueryparams">toQueryParams</a> says:</p>

<blockquote>
  <p>Parses a URI-like query string and returns an object composed of parameter/value pairs.</p>
</blockquote>

<p>Since it's a URI-like query string and not an actual query string (by which I mean one that's been through the browser address bar and as such subject to whatever text munging the browser does), my example above should be a legal use case.</p>

<p>After a little digging around in prototype.js, it seems that the problem is caused by the JavaScript function decodeURIComponent() not enjoying being given a string that contains an unescaped percent symbol.  Usually percent symbols are used in conjunction with a number to represent a non-alphanumeric character in a URL - %20 for space, etc, but in the above it's a literal percent symbol.</p>

<p>My first attempt to fix it changed lines 98 and 100 of string.js in the Prototype source to use the built in <a href="http://www.w3schools.com/jsref/jsref_escape.asp">escape</a> function:</p>

<pre class="prettyprint linenums">
var key = decodeURIComponent(pair.shift());
...
if (value != undefined) value = decodeURIComponent(value);
</pre>

<p>to</p>

<pre class="prettyprint linenums">
var key = decodeURIComponent(escape(pair.shift()));
...
if (value != undefined) value = decodeURIComponent(escape(value));
</pre>

<p>This worked for my use case but caused Prototype to fail a different unit test.  Changing them to the following worked out okay:</p>

<pre class="prettyprint linenums">
var key = unescape(decodeURIComponent(escape(pair.shift())));
...
if (value != undefined) value = unescape(decodeURIComponent(escape(value)));
</pre>

<p>Granted the unescape(...(escape(...)) is a little clumsy, but it seems to get the job done.</p>

<p>Adding the following unit test to string.html allows to test for the above:</p>

<pre class="prettyprint linenums">
this.assertHashEqual({'key1': 'va%lue1'}, 'key1=va%lue1'.toQueryParams(), 'rogue percent symbol test');
</pre>

<p>I've created some <a href="http://www.achingbrain.net/files/prototype_toQueryParams_bug/">test pages</a> which demonstrate the problem.</p>

<p>There is also a <a href="http://www.achingbrain.net/files/prototype_toQueryParams_bug/string.js.patch">patch file</a> available.  Apply it to /src/string.js in your Prototype source tree.</p>

<p><strong>Update</strong></p>

<p>I've also <a href="http://prototype.lighthouseapp.com/projects/8886/tickets/15-patch-test-string-toqueryparams-not-handling-properly">filed a bug</a></a>.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Code]]></title>
			<link>http://achingbrain.net/code</link>
			<guid>http://achingbrain.net/code</guid>
			<pubDate>Fri, 11 Apr 2008 14:40:45 +0100</pubDate>
			<description><![CDATA[<p>I haven't posted here for a while, mainly due to the time sink that is Facebook, but I have been writing code in my spare time, honest.  I thought I'd have a little skim through what's on my machine and share a few choice nuggets.</p>

<p>Recently I've been trying to get into programming applications for Mac OS X - I use it on a day to day basis so thought it would be best to get involved.  I've put some new things on the <a href="http://www.achingbrain.net/stuff">Stuff</a> page for your perusal.  They are:
<h3><a href="http://www.achingbrain.net/stuff/cocoa/applications/backgrounderer">Backgrounderer</a></h3>
A little app to download desktop wallpapers from veer.com.  If you wish to build from source, you'll need to install <a href="http://regexkit.sourceforge.net/">RegexKit</a> first.
<h3><a href="http://www.achingbrain.net/stuff/cocoa/applications/mail-rss-exporter">Mail RSS Exporter</a></h3>
An application that exports your RSS feeds from Apple Mail and stores them in either OPML format or Safari Bookmarks.
<h3><a href="http://www.achingbrain.net/stuff/cocoa/applications/touch-me">TouchMe</a></h3>
A program to run AppleScripts on a computer on your local network from your iPhone or iPod Touch - I use this to control a Mac mini attached to a projector.  The projector is not always switched on so Front Row was insufficient.  It also allows you to force quit applications that have hung.
<h3><a href="http://www.achingbrain.net/stuff/cocoa/frameworks/simplehttpd">SimpleHTTPd</a></h3>
A Cocoa native web server packaged as a framework so you can use it in your own projects.  Based on Jurgen Schwiezer's <a href="http://www.oreilly.com/pub/a/mac/2006/11/14/how-to-write-a-cocoa-web-server.html">SimpleHTTPServer</a>.</p>

<p>All of the above require OS X 10.5 Leopard as coming from a Java/PHP background I have a strange fetish for garbage collectors and consequently find manual memory management tedious.</p>

<p>They are all BSD licensed and source is included with each program so go crazy.</p>

<p>I'll get round to posting about each one in more depth in the near future.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[TouchMe screenshot]]></title>
			<link>http://achingbrain.net/touchme</link>
			<guid>http://achingbrain.net/touchme</guid>
			<pubDate>Thu, 10 Apr 2008 17:25:53 +0100</pubDate>
			<description><![CDATA[
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Mail RSS Exporter screenshot]]></title>
			<link>http://achingbrain.net/mailrssexporter</link>
			<guid>http://achingbrain.net/mailrssexporter</guid>
			<pubDate>Thu, 10 Apr 2008 17:17:39 +0100</pubDate>
			<description><![CDATA[
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Java OSC]]></title>
			<link>http://achingbrain.net/java-osc</link>
			<guid>http://achingbrain.net/java-osc</guid>
			<pubDate>Tue, 01 Apr 2008 12:58:14 +0100</pubDate>
			<description><![CDATA[<h3>Important update!</h3>

<p>Please note that <a href="http://www.illposed.com/software/javaosc.html">a new version of JavaOSC</a> has been released that includes the patches below.  Please use the new release in preference to patching old versions of the source.  This page remains here purely for informational purposes, or posterity, or something like that.
<ul>
    <li><a href="#introduction">Introduction</a></li>
    <li><a href="#download">Download</a></li>
    <li><a href="#compilation">Compilation</a></li>
    <li><a href="#installation">Installation</a></li>
    <li><a href="#usage">Usage</a></li>
</ul>
<h3><a title="introduction" name="introduction" id="introduction"></a>Introduction</h3>
The problem:  if you use <a href="http://www.mat.ucsb.edu/~c.ramakr/illposed/javaosc.html">JavaOSC</a> and send a BigInteger object down the pipe, you get an Integer object at the other end, and suffer the associated loss of accuracy with going from a 64bit number to a 32bit number.</p>

<p>This may not be a problem for most, but if you are using the number for, say, insanely accurate timing data, it's a pain in the behind.</p>

<p>The solution:  a small patch to the source code.</p>

<p><strong>Please note</strong> - this patch will probably be incoporated into the next release of JavaOSC, so no worries about upgrading..
<h3><a title="download" name="download" id="download"></a>Download</h3>
<a href="/files/JavaOSC/JavaOSC-patch.tar.gz">The patch files</a> 650B
<a href="/files/JavaOSC/JavaOSC-patched-source.tar.gz">A pre-patched version of the source</a> 38K
<a href="/files/JavaOSC/JavaOSC-jar.tar.gz">A pre-built .jar</a> 40K
<h3><a title="installation" name="installation" id="compilation"></a>Compilation</h3>
If you downloaded the patch files, copy them to the '/src/com/illposed/osc/utility/' directory under where you extraced the original JavaOSC source (<a href="http://www.mat.ucsb.edu/~c.ramakr/illposed/javaosc.html">get a copy of the source from here</a>) and from that directory, run the following commands:</p>

<pre><code lang="bash">patch OSCByteArrayToJavaConverter.java &lt; OSCByteArrayToJavaConverter.java.patch
patch OSCJavaToByteArrayConverter.java &lt; OSCJavaToByteArrayConverter.java.patch
rm ./*.patch
cd ../../../../../
ant</code></pre>

<p>You may also need to edit OSCBundle.java and OSCMessage.java in the directory /src/com/illposed/osc/ to get it to compile under Java 1.5 - just change the variable named 'enum' to something like 'vecEnum' throughout the two source files and you should be fine.</p>

<p>The above assumes you are either on Linux or OS X.  If you are on Windows, google for an alternative to patch, or open the patch files in notepad and make the changes manually (there aren't very many..).</p>

<p>If you downloaded the patched source, untar the archive and build with ant as normal.</p>

<p>If you downloaded the .jar file, no compilation is necessary - jump straight to the installation instructions.
<h3><a title="installation" name="installation" id="installation"></a>Installation</h3>
Put the resulting javaosc.jar file in the jre/lib/ext/ directory of your Java install.  Mine lives at /opt/sun-jdk-1.5.0.06/jre/lib/ext/  Yours may be at C:/Program Files/Java/jdk1.5.0_06/jre/lib/ext/ or /System/Library/Java/Extensions/ or somewhere else.  It's a mystery.
<h3><a title="usage" name="usage" id="usage"></a>Usage</h3>
No special instructions here, just treat it like you would the unpatched JavaOSC version, but enjoy the 64bit goodness.</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Java]]></title>
			<link>http://achingbrain.net/java</link>
			<guid>http://achingbrain.net/java</guid>
			<pubDate>Tue, 01 Apr 2008 12:57:49 +0100</pubDate>
			<description><![CDATA[<h2>Auditorium</h2>

<p><p>My final year project for College.  Auditorium is a system for turning musical input in to a stream of data that can be used to generate highly specific visuals, movement, animation  or other effects.
<a href="http://www.auditorium-project.org.uk">Check it out. ¬ª</a></p>
<h2>Java OSC</h2>
<p>A small patch to the otherwise excellent <a href="http://www.mat.ucsb.edu/~c.ramakr/illposed/javaosc.html">Java implementation</a> of Open Sound Control by Chandrasekhar Ramakrishnan.  This patch ensures that when you hand an OSCPortOut object a BigInteger, you get a BigInteger from the OSCPortIn object at the other end.  <strong>Please note that the <a href="http://www.illposed.com/software/javaosc.html">current JavaOSC release</a> already includes this patch.</strong>
<a href="/stuff/java/java-osc/">Check it out. ¬ª</a></p></p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[Touch Me]]></title>
			<link>http://achingbrain.net/touch-me</link>
			<guid>http://achingbrain.net/touch-me</guid>
			<pubDate>Tue, 01 Apr 2008 12:54:43 +0100</pubDate>
			<description><![CDATA[<ul>
    <li><a href="#introduction">Introduction</a></li>
    <li><a href="#download">Download</a></li>
    <li><a href="#installation">Installation</a></li>
    <li><a href="#usage">Usage</a></li>
    <li><a href="#changelog">Changelog</a></li>
</ul>

<p><h3><a name="introduction"></a>Introduction</h3>
TouchMe is a little app I knocked up to control my media server (a Mac mini) from my iPhone or an iPod Touch.  It uses my <a href="http://www.achingbrain.net/stuff/cocoa/frameworks/simplehttpd">SimpleHTTPd</a> Cocoa web server to serve a webapp to connecting clients.</p>

<p>Plugins for various applications are written as XML files containing AppleScript commands that are executed on the server to control their respective applications.  The plugins are loaded by a System Preferences panel.
<h3><a name="download"></a>Download</h3>
Source is included in the download.  This application requires Mac OS 10.5 Leopard or above as it uses features of Objective C 2.0 including the garbage collector.
<ul>
    <li><a href="http://www.achingbrain.net/files/TouchMe/TouchMe.dmg">TouchMe</a> 3.8MB</li>
</ul>
<h3><a name="installation"></a>Installation</h3>
Double click the DMG and drag the application to your desktop or /Applications directory.  Double click the preferences panel to load it into your System Preferences application.</p>

<p>Finally, use the preferences panel to import plugins from the plugins folder and start/restart the application.
<h3><a name="usage"></a>Usage</h3>
By default TouchMe runs on port 9001 on the server.  It advertises itself via Bonjour Bookmarks (a bookmark menu in Safari) so connecting from a desktop machine should be quite straightforwad, however currently Mobile Safari does not support Bonjour Bookmarks (although I believe it's slated for version 2 of the firmware) so you'll have to key in the IP address manually.</p>

<p>It is not currently possible to change the port TouchMe runs on but I may add it in a later release if it is requested.</p>

<p>Once you have accessed the page it presents a list-style interface that should be familiure to iPhone/iPod Touch users.</p>

<p><img class="aligncenter size-full wp-image-164" title="TouchMe screenshot" src="http://www.achingbrain.net/wp-content/uploads/2008/04/touchme.jpg" alt="" width="320" height="480" />
<h4>Writing plugins</h4>
Plugins are simply XML files with a different extension.  Open the file in a text editor (I like <a href="http://smultron.sourceforge.net/">Smultron</a> but TextEdit will do - just make sure to turn off text formatting) and ensure that it looks similar to the following:
<pre lang="XML">
<?xml version="1.0"?>
<plugin>
    <name>iTunes</name>
    <description>Play it loud, OK?</description>
    <version>0.1</version>
    <application>iTunes</application>
    <command>
        <name>Play/Pause</name>
        <exec>&lt;![CDATA[ tell application "iTunes" to playpause ]]></exec>
    </command>
    <command>
        <name>Next track</name>
        <exec>&lt;![CDATA[ tell application "iTunes" to next track ]]></exec>
    </command>
    <command>
        <name>Previous track</name>
        <exec>&lt;![CDATA[ tell application "iTunes" to previous track ]]></exec>
    </command>
</plugin>
</pre>
The contents of the <code>name</code> tag should be unique within TouchMe as it's used to build the menu structure.</p>

<p><code>description</code> is used to give a sub heading and <code>version</code> to keep track of, well, the version number - it's displayed in the System Preferences application.</p>

<p><code>application</code> should be the name of the application that the plugin controls (without the .app extension) and is used to start, stop and force quit the application.</p>

<p>The available AppleScript commands are defined by any number of <code>command</code> tags.  The <code>name</code> tag is displayed in the interface and the contents of the <code>exec</code> tags are internally passed to the command line <code>osascript</code> program to actually execute the command.  Multi line scripts are supported.  Wrapping the AppleScript in <code>CDATA</code> tags is optional but is advised.</p>

<p>The commands are passed in as-is so while it's technically possible to control more than one application from a plugin that sort of thing is discouraged.</p>

<p>When you are done editing, save the file with the extension .touchme and use the System Preferences panel to import your new plugin - TouchMe should then be restarted automatically.  Reload the page in Safari and try it out.</p>

<p>If you come up with a neat plugin, <a href="http://www.achingbrain.net/contact">send it to me</a> and I'll create a page for them.
<h3><a name="changelog"></a>Changelog</h3>
<h4>Version 0.2</h4>
Initial release
<h4>Version 0.1</h4>
Internal testing version</p>
]]></description>
		</item>
 
		<item>
			<title><![CDATA[SimpleHTTPd]]></title>
			<link>http://achingbrain.net/simplehttpd</link>
			<guid>http://achingbrain.net/simplehttpd</guid>
			<pubDate>Tue, 01 Apr 2008 12:29:02 +0100</pubDate>
			<description><![CDATA[<ul>
    <li><a href="#introduction">Introduction</a></li>
    <li><a href="#download">Download</a></li>
    <li><a href="#installation">Installation</a></li>
    <li><a href="#usage">Usage</a></li>
    <li><a href="#changelog">Changelog</a></li>
</ul>

<p><h3><a id="introduction" title="introduction" name="introduction"></a>Introduction</h3>
This is a simple web server written in Objective C/C using the Cocoa/Core Foundation and packaged up as a Framework for inclusion in your own projects.</p>

<p>It's based on <a href="http://culturedcode.com/cocoa/">SimpleHTTPServer</a> written by Jurgen of Cultured Code (ace Mac developer of <a href="http://culturedcode.com/things/">Things</a> fame) and the <a href="http://www.oreilly.com/pub/a/mac/2006/11/14/how-to-write-a-cocoa-web-server.html">article</a> he wrote for O'Reilly's Mac Dev Center.  The improvements I've made include handling POST requests, handling requests split over multiple packets, changing the listening port, the web root, and advertising the server via Bonjour.
<h3><a id="download" title="download" name="download"></a>Download</h3>
Source is included in the download. This application requires Mac OS 10.5 Leopard or above as it uses features of Objective C 2.0 including the garbage collector.
<ul>
    <li><a href="http://www.achingbrain.net/files/SimpleHTTPd/SimpleHTTPd.dmg">SimpleHTTPd</a> 68KB</li>
</ul>
<h3><a id="installation" title="installation" name="installation"></a>Installation</h3>
Open the DMG and use XCode to import the framework into your project.</p>

<p>Ensure that it is copied into your application bundle as part of the build phase.
<h3><a id="usage" title="usage" name="usage"></a>Usage</h3>
See the following for an example:
<pre lang="objc">// create the object
SimpleHTTPResponder  *simpleHTTPResponder = [[SimpleHTTPResponder alloc] init];</p>

<p>// listen on port 80
[simpleHTTPResponder listen:80];</p>

<p>// where to serve files from - in this case, a folder
// called "httpdocs" under "resources" in the
// application bundle
[simpleHTTPResponder setWebRoot:[[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingString:@"/httpdocs"]];</p>

<p>// set the index file
[simpleHTTPResponder setIndexFile:@"index.html"];</p>

<p>// open port and wait for requests
[simpleHTTPResponder startListening];</pre>
<h4>Bonjour publishing</h4>
To broadcast the availability of your server on the local network, use the following method:
<pre lang="objc">// set the service name for Bonjour
[simpleHTTPResponder publish:@"MyWebsite"];</pre>
Pass in any string you like and it should show up in Bonjour aware application such as Safari's "Bonjour Bookmarks" list.
<h4>Server delegate</h4>
The default behaviour of SimpleHTTPd on receipt of a request is to look in the specified web root folder for the requested file - if it finds it, the file will be piped to the user, otherwise a 404 will be sent.  To implement more advanced functionality, we need to set a delegate object to process incoming requests.  This is done via the following method:
<pre lang="objc">// set the object that will respond to requests
[simpleHTTPResponder setDelegate:myResponder];</pre>
The object passed to <code>setDelegate</code> should implement the category SimpleHTTPWillRespond (found in SimpleHTTPResponder.h).  This prototcol defines two methods:
<pre lang="objc">- (SimpleHTTPResponse *)processPOST:(SimpleHTTPRequest *)request;
- (SimpleHTTPResponse *)processGET:(SimpleHTTPRequest *)request;</pre>
In the simplest case just call the default methods on the server object we created above:
<pre lang="objc">- (SimpleHTTPResponse *)processPOST:(SimpleHTTPRequest *)request
{
    return [simpleHTTPResponder processRequest:request];
}</p>

<ul>
<li>(SimpleHTTPResponse *)processGET:(SimpleHTTPRequest *)request
{
return [simpleHTTPResponder processRequest:request];
}</pre>
Otherwise you'll want to examine the SimpleHTTPRequest object.
<h4>Responding to a request</h4>
If you wish to override the default behaviour, first, have a look at the public methods exposed by the SimpleHTTPRequest object:
<pre lang="objc">// returns the requested URL</li>
<li>(NSURL *)url;</li>
</ul>

<p>// POST or GET
- (NSString *)method;</p>

<p>// The headers that accompany the request
- (NSDictionary *)headers;</p>

<p>// Get an individual header
- (NSString *)getHeader:(NSString *)byName;</p>

<p>// The body of the request
// e.g. in the case of POST, the raw POST query string
- (NSData *)body;</p>

<p>// The current connection
- (SimpleHTTPConnection *)connection;</p>

<p>// The time of the request
- (NSDate *)date;</p>

<p>// Get a POST variable by name
- (NSString *)postVar:(NSString *)byName;</p>

<p>// Get a GET variable by name
- (NSString *)getVar:(NSString *)byName;</pre>
The request handler methods need to return a SimpleHTTPResponse object.  HTTP responses are made up of headers and optionally a response body.  The relevant setter methods exposed by a SimpleHTTPResponse object are:
<pre lang="objc">
// Adds a header to the repsonse
- (void)addHeader:(NSString *)key withValue:(NSString *)value;</p>

<p>// Defaults to "text/html"
- (void)setContentType:(NSString *)mimeType;</p>

<p>// Defaults to 200
- (void)setResponseCode:(int)code;</p>

<p>// Sets the response body (e.g. read in binary file data or similar)
- (void)setContent:(NSData *)toData;</p>

<p>// A convenience method for sending back text (e.g. HTML)
- (void)setContentString:(NSString *)toString;
</pre>
So you could do something like the following:
<pre lang="objc">- (SimpleHTTPResponse *)processPOST:(SimpleHTTPRequest *)request
{
    if([request getHeader:@"magicHeader"] != NULL) {
        SimpleHTTPResponse *response = [[SimpleHTTPResponse alloc] init];
        [response setContentString:@"You sent a magic header"];</p>

<pre><code>    return response;
}

return [simpleHTTPResponder processRequest:request];
</code></pre>

<p>}</pre>
Please <a href="/contact">send me</a> any comments/suggestions.
<h3><a id="changelog" title="changelog" name="changelog"></a>Changelog</h3>
<h4>Version 0.2</h4>
Initial release
<h4>Version 0.1</h4>
Internal testing version</p>
]]></description>
		</item>
	</channel>
</rss>