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

<channel>
	<title>Psychic Origami</title>
	<atom:link href="http://psychicorigami.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://psychicorigami.com</link>
	<description>folding with my brain</description>
	<pubDate>Wed, 23 Jul 2008 19:00:15 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Splitting your Turbogears SQLObject models</title>
		<link>http://psychicorigami.com/2008/07/21/splitting-your-turbogears-sqlobject-models/</link>
		<comments>http://psychicorigami.com/2008/07/21/splitting-your-turbogears-sqlobject-models/#comments</comments>
		<pubDate>Mon, 21 Jul 2008 18:38:43 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Python]]></category>

		<category><![CDATA[sqlobject]]></category>

		<category><![CDATA[turbogears]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=147</guid>
		<description><![CDATA[Just a quick note about splitting you model.py file in Turbogears 1.0, when using SQLObject.  The Turbogears docs have some notes on this, but there was an extra trick to it in the end.
The model.py file for chrss, was starting to get a bit big, so it seemed like a good time to do [...]]]></description>
			<content:encoded><![CDATA[<p>Just a quick note about splitting you <code>model.py</code> file in <a href='http://turbogears.org/'>Turbogears</a> 1.0, when using <a href='http://sqlobject.org/'>SQLObject</a>.  The Turbogears docs have <a href='http://docs.turbogears.org/1.0/CreatingBigApplications#splitting-the-model'>some notes</a> on this, but there was an extra trick to it in the end.</p>
<p>The <code>model.py</code> file for <a href='http://chrss.co.uk/'>chrss</a>, was starting to get a bit big, so it seemed like a good time to do this.</p>
<p>First I moved <code>model.py</code> into <code>model/__init__.py</code>.  Then I moved all of the model code itself into separate files (three as it happens) and imported them into <code>model/__init__.py</code> as indicated in the Turbogears docs:</p>
<pre><code>
from chrss.model.cms import *
from chrss.model.chess import *
from chrss.model.base import *
</code></pre>
<p>However that wasn&#8217;t enough, as the <code>__connection__</code> module level variable for SQLObject wasn&#8217;t set and Turbogears couldn&#8217;t connect to the DB.  So I added this to <code>model/__init__.py</code> (<em>before the other imports</em>):</p>
<pre><code>
from turbogears.database import PackageHub

hub = PackageHub("chrss")
</code></pre>
<p>and then in each file containing models added the following:</p>
<pre><code>
from chrss.model import hub
__connection__ = hub
</code></pre>
<p>The main trick was to get the import order correct.  <code>model/__init__.py</code> must declare the <code>hub</code> variable, before importing the other files, so that they can access it when they are imported.  It&#8217;s a bit of a cyclical dependency, which is maybe not ideal, but it&#8217;s only used in a limited way.</p>
<p><strong>UPDATE</strong>.  It turns out that you also need to update the <code>sqlobject.txt</code> file in the <code>.egg-info</code> directory of your project.  Otherwise the various <code>tg-admin sql *</code> commands don&#8217;t work (as it can&#8217;t find the SQLObject classes).  Basically you have to list every sub-package of the newly split model package. e.g. change:</p>
<pre><code>
db_module=chrss.model
</code></pre>
<p>to:</p>
<pre><code>
db_module=chrss.model,chrss.model.base,chrss.model.chess,chrss.model.cms
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/07/21/splitting-your-turbogears-sqlobject-models/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A Second Chumby Widget</title>
		<link>http://psychicorigami.com/2008/07/17/a-second-chumby-widget/</link>
		<comments>http://psychicorigami.com/2008/07/17/a-second-chumby-widget/#comments</comments>
		<pubDate>Thu, 17 Jul 2008 18:33:28 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[chumby]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=143</guid>
		<description><![CDATA[I finally had a chance to do some more Actionscript coding for the Chumby again.  The last widget I did was the bare minimum to get going and this one is only a little more advanced.  In particular it&#8217;s a simple analogue clock.  All it does is show the current time, nothing [...]]]></description>
			<content:encoded><![CDATA[<p>I finally had a chance to do some more Actionscript coding for the <a href='http://chumby.com/'>Chumby</a> again.  The <a href='http://psychicorigami.com/2008/05/29/hello-chumby-a-first-widget/'>last widget</a> I did was the bare minimum to get going and this one is only a little more advanced.  In particular it&#8217;s a simple analogue clock.  All it does is show the current time, nothing more, but it does involve a few more &#8220;moving parts&#8221; than were involved in the &#8220;Hello World&#8221; widget from last time.</p>
<p>So to start off with here&#8217;s the scaled down scan I used for the clock face and hands:</p>
<p><center><a href='http://psychicorigami.com/wp-content/uploads/2008/07/clock_parts.png'><img src="http://psychicorigami.com/wp-content/uploads/2008/07/clock_parts.png" alt="" title="clock_parts" width="427" height="240" class="alignnone size-full wp-image-145" /></a></center></p>
<p>I cut out the face and hands and put them into separate files (see .tar.gz below) for using in the Actionscript.  All images were 24bit PNGs with variable alpha transparency, so that the edges look nice and smooth on the Chumby screen (which is relatively low resolution).</p>
<p>The Actionscript (<code>ChumbyClock.as</code>) is very simple and looks like this:</p>
<p><code>
<pre>

class ChumbyClock extends MovieClip {
	var hourHand:MovieClip;
	var minHand:MovieClip;
	var secHand:MovieClip;

	function onLoad() {
		this.hourHand = loadHand('hour_hand');
		this.minHand  = loadHand('minute_hand');
		this.secHand  = loadHand('second_hand');
	}

	function loadHand(hand_id:String) {
		var clip = this.createEmptyMovieClip("clip", this.getNextHighestDepth());
		clip._x = 160;
		clip._y = 120;

		// load image an shift it to be in 12 o'clock position
		// with 0,0 as middle of bottom of image
		var hand = clip.attachMovie(hand_id, 'hand', clip.getNextHighestDepth());
		hand._x = -hand._width/2;
		hand._y = -hand._height + (hand._width/2);
		return clip;
	}

	function toDegrees(val:Number, range:Number) {
		return (360*(val % range))/range;
	}

	function onEnterFrame() {
		var now:Date = new Date();

		var sec:Number = now.getSeconds();
		secHand._rotation = toDegrees(sec, 60);

		var min:Number = now.getMinutes();
		minHand._rotation = toDegrees(min, 60);

		// let hour hand move a little bit with min hand
		var hourWithMin:Number = now.getHours() + min/60.0;
		hourHand._rotation = toDegrees(hourWithMin, 12);
	}

}
</pre>
<p></code></p>
<p>All this does is create three movies which contain the hand images, placed so they are in the 12 O&#8217;Clock position.  At each timestep (<code>onEnterFrame</code>) the current time is queried and the hand rotations are updated.  The second and minute hands are just rotated in proportion with the relevant values.  The hour hand is also slightly rotated with the current minute.  As we get nearer the end of the hour, the hour hand moves nearer to the next hour.  Much as you&#8217;d expected for a real clock.  That&#8217;s it.  I did play around with having smoother animation for the hands, but it looked a bit eery.</p>
<p>To tie the Actionscript and images together there is an xml file (<code>app.xml</code>) used by <code>swfmill</code>:</p>
<p><code>
<pre>
&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;movie width="320" height="240" framerate="12"&gt;
  &lt;background color="#ffffff"/&gt;
  &lt;clip import="build/classes.swf" /&gt;

  &lt;frame&gt;
    &lt;library&gt;
      &lt;clip id="face"        import="images/hand_drawn/face.png" /&gt;
      &lt;clip id="hour_hand"   import="images/hand_drawn/hour_hand.png"  /&gt;
      &lt;clip id="minute_hand" import="images/hand_drawn/minute_hand.png"/&gt;
      &lt;clip id="second_hand" import="images/hand_drawn/second_hand.png"/&gt;
      &lt;clip id="app" class="ChumbyClock" /&gt;
    &lt;/library&gt;

    &lt;place id="face" name="clockFace" depth="0" /&gt;
    &lt;place id="app" name="myApp" depth="1" /&gt;
  &lt;/frame&gt;
&lt;/movie&gt;
</pre>
<p></code></p>
<p>This will allow us to embed the PNGs in the generated SWF file and reference them from the Actionscript.  In addition the clock face image is placed statically behind the main movie of the hands.</p>
<p>These files are then run through a build script to generate the SWF:</p>
<p><code>
<pre>
~/bin/mtasc-1.12-osx/mtasc -swf build/classes.swf -header 320:240:12 ChumbyClock.as
~/bin/swfmill-0.2.12-macosx/swfmill simple app.xml chumbyclock.swf
</pre>
<p></code></p>
<p>Here&#8217;s the generated SWF:</p>
<p><center><br />
<embed style="border: 1px solid black" src="http://psychicorigami.com/wp-content/uploads/2008/07/chumbyclock.swf" width="320" height="240" /><br />
</center></p>
<p>To test this on the Chumby I put the SWF on a memory stick along with this <code>debugchumby</code> script:</p>
<p><code>
<pre>
#!/bin/sh
chumbyflashplayer.x -i /mnt/usb/chumbyclock.swf
</pre>
<p></code></p>
<p>Then when the Chumby is rebooted with the memory stick in the clock displays and all is good.</p>
<p>So there you go that&#8217;s a simple clock widget for the Chumby - using open source tools.</p>
<p><a href='http://psychicorigami.com/wp-content/uploads/2008/07/chumbyclocktar.gz'>Download Widget Source Code and Images.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/07/17/a-second-chumby-widget/feed/</wfw:commentRss>
		</item>
		<item>
		<title>LOGON: Joshua</title>
		<link>http://psychicorigami.com/2008/06/08/logon-joshua/</link>
		<comments>http://psychicorigami.com/2008/06/08/logon-joshua/#comments</comments>
		<pubDate>Sun, 08 Jun 2008 07:36:02 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[Artwork]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=141</guid>
		<description><![CDATA[
Seeing as Wargames turned 25 years old this week, it seemed like a good time to do a drawing of David Lightman (Mr Broderick) just as he logs into WOPR for the first time.  It&#8217;s a classic moment in the film and shows a slightly more realistic view on hacking/cracking.  None of this [...]]]></description>
			<content:encoded><![CDATA[<p><center><a href='http://psychicorigami.com/wp-content/uploads/2008/06/wargames.gif'><img src="http://psychicorigami.com/wp-content/uploads/2008/06/wargames-300x211.gif" alt="" title="LOGON: Joshua" width="300" height="211" class="alignnone size-medium wp-image-142" /></a></center></p>
<p>Seeing as <a href='http://www.imdb.com/title/tt0086567/'>Wargames</a> turned 25 years old this week, it seemed like a good time to do a drawing of David Lightman (Mr Broderick) just as he logs into WOPR for the first time.  It&#8217;s a classic moment in the film and shows a slightly more realistic view on hacking/cracking.  None of this &#8220;re-routing the encryption codes&#8221; nonsense.  Good old-fashioned sleuthing and intuition instead.</p>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/06/08/logon-joshua/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A turbogears caching decorator</title>
		<link>http://psychicorigami.com/2008/05/31/a-turbogears-caching-decorator/</link>
		<comments>http://psychicorigami.com/2008/05/31/a-turbogears-caching-decorator/#comments</comments>
		<pubDate>Sat, 31 May 2008 15:39:42 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[Chrss]]></category>

		<category><![CDATA[Development]]></category>

		<category><![CDATA[Python]]></category>

		<category><![CDATA[turbogears]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=139</guid>
		<description><![CDATA[A while back I wrote a caching decorator for chrss.  It&#8217;s mostly used for the rss feeds, to help avoid having over-zealous rss readers slowing the site down.  However I&#8217;m also now running it on a few other pages that were a bit slow (notably generating PGN files for games).
After letting it sit [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href='http://chrss.co.uk/blog/avatars-bios-and-caching'>while back</a> I wrote a caching decorator for <a href='http://chrss.co.uk'>chrss</a>.  It&#8217;s mostly used for the rss feeds, to help avoid having over-zealous rss readers slowing the site down.  However I&#8217;m also now running it on a few other pages that were a bit slow (notably generating <a href='http://en.wikipedia.org/wiki/Portable_Game_Notation'>PGN</a> files for games).</p>
<p>After letting it sit for a while Ian and Kyran also started using it on <a href='http://showmedo.com/'>ShowMeDo</a>.  That was a couple of months ago.  So now that I can be fairly certain it works it seemed like time to share it with the world.</p>
<p>So first off here&#8217;s a few features/comments:</p>
<ul>
<li>It&#8217;s shamelessly based on code from <a href='http://www.djangoproject.com/'>Django</a> (the caching backends at least)</li>
<li>It features an &#8220;anti-dogpiling&#8221; mechanism to try and make sure only one thread triggers a cache refresh</li>
<li>Multiple backends supported:</li>
<ul>
<li><code>dummy</code> - does no caching (for testing/development use)</li>
<li><code>simple</code> - just uses a dictionary (for testing/development use)</li>
<li><code>localmem</code> - thread-safe cache for use in process</li>
<li><code>file</code> - uses file-system to cache data (this is what&#8217;s used with chrss and ShowMeDo)</li>
<li><code>memcache</code> - uses memcached for caching (it should work, but not massively tested at the moment)</li>
</ul>
</ul>
<p>Now for some example usage:</p>
<pre><code>
from turbogears import expose, controllers
from cache import cache_result

class MyController(controllers.Controller):

    @expose(content_type="text/plain")
    @cache_result()
    def cache_some_text(self):
        ''' no template so it's pretty straightforward - expose just has to come first '''
        return 'this will be cached'

    @expose(template="my_template)
    @cache_result()
    def cache_data_only(self):
        ''' with a template we can just cache the data and not rendered html '''
        return dict(value='this dictionary will be cached')

    @expose()
    @cache_result()
    @expose(template="my_template)
    def cache_html(self):
        '''
        or we can cache the rendered html, but we have to use an outer expose()
        to make the method public
        '''
        return dict(value='will be cached with the html')

</code></pre>
<p>To see how you can use the <code>@cache_result()</code> you are probably best looking<br />
at the source (there&#8217;s a fairly detailed comment explaining it).  The following parameters can<br />
be passed in:</p>
<ul>
<li><code>key_fn</code> - function used to derive a key to store the data in (default uses current url and user identity)</li>
<li><code>version_fn</code> - can be used to control how a cached value expires (defaults to a function that returns the same value everytime)</li>
<li><code>timeout_seconds</code> - how many seconds until the value start to expire</li>
</ul>
<p>The default key function can be controlled via the config parameter <code>cache.decorator.anon_only</code>.  If set to <code>True</code> (the default) it will only look in the cache for data when users are not logged in.  Otherwise when users are logged in it will use a key just for them.  The default is handy if you just want to avoid problems with a flood of anonymous users (e.g. from Slashdot/Digg etc).</p>
<p>The version function can be used to force expire cached values.  The value of the version function is compared to the value stored in the cache and if different this triggers a cache refresh.  For example if the version function was based on the number of comments in a blog post, then whenever a comment was added to the blog post the cache would get refreshed.  This avoids having to wait for the cache to expire.</p>
<p><code>timeout_seconds</code> specifies how many seconds before a value expires.  It defaults to the value set in <code>cache.decorator.timeout_seconds</code> in your config file (or 1800 seconds if not set there).</p>
<h3>anti-dogpiling</h3>
<p>So first I&#8217;ll explain what I mean by &#8220;dogpiling&#8221; with respect to cache expiry.</p>
<p>The standard way to use a cache is to do something like:</p>
<pre><code>
value = cache.get('key', None)
if value is None:
    value = recompute_cached_value()
    cache['key'] = value
return value
</code></pre>
<p>Now this is fine normally.  When the cached value expires the next request will simply call <code>recompute_cached_value()</code> and the cache will be updated for future requests.</p>
<p>The trouble arises when <code>recompute_cached_value()</code> takes a long time to run and you have have a lot of other requests running at the same time.  If a request is still recalculating the value and another request comes along, then that will also attempt to recalculate the value.  This will in turn probably slow down the calculation going on, making it more likely that the next request to arrive will also trigger a recalculation and so on.  Very quickly you can end up with tens/hundreds/thousands of request all attempting to recalculate the cached value and you have lost most of the advantage of caching in the first place.</p>
<p>So to handle this situation more gracefully this caching decorator employs a two stage expiry.</p>
<p>First there is a hard cut off expiry that works like normal.  This is set to occur later than the other expiry time and is the value that would be fed to memcache or equivalent.</p>
<p>The second expiry time set is the one normally used.  Basically when we store/retrieve the cached data we also have access to this expiry time (and the version).  If we see that we need to recalculate the value (due to the expiry time being in the past or the version being different), then we attempt to grab a lock to recalculate the value.  If we don&#8217;t grab the lock, we assume another thread is doing the recalculation and rather than wait around we simply serve up the old (stale) data.  This should mean that one thread (potentially per-process) will end up doing the recalculation rather than several.</p>
<p>This also means that we don&#8217;t have to remove a value from the cache to force a refresh (which might cause dogpiling).  Instead we can update whatever value we use in our version function, to trigger a graceful refresh.</p>
<h3>conclusion</h3>
<p>So that&#8217;s a basic intro to this caching decorator.  It&#8217;s quite a handy quick way of adding some caching to your <a href='http://turbogears.org/'>turbogears</a> app.  You&#8217;ll need to see how well it works for you.  I&#8217;m providing it &#8220;as is&#8221; and making no claims about anything.  Feel free to incorporate it into your code and modify as you see fit.  Just let me know if you have any issues or feedback.</p>
<h3>bonus decorator</h3>
<p>The cache code also includes a simple decorator to control the <code>Expires</code> header sent out with a response:</p>
<pre><code>
def expires(seconds=0):
    '''set expire headers for client-size caching'''
    def decorator(fn):
        def decorated(*arg,**kw):
            cherrypy.response.headers['Expires']=formatdate(_current_time()+seconds)
            return fn(*arg,**kw)
        return decorated
    return decorator
</code></pre>
<p>It&#8217;s handy for getting the client to cache some data for us too.  I use it on some of the <a href='http://www.pythonware.com/products/pil/'>PIL</a> generated images served up via my app.</p>
<h3>source code</h3>
<p><a href='http://psychicorigami.com/source/tg_cache.tar.gz'>Download turbogears caching decorator</a></p>
<p>The source for the decorator(s) includes a simple test suite (to be run using <a href='http://www.somethingaboutorange.com/mrl/projects/nose/'>nose</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/05/31/a-turbogears-caching-decorator/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Hello Chumby! (a first widget)</title>
		<link>http://psychicorigami.com/2008/05/29/hello-chumby-a-first-widget/</link>
		<comments>http://psychicorigami.com/2008/05/29/hello-chumby-a-first-widget/#comments</comments>
		<pubDate>Thu, 29 May 2008 19:33:06 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[chumby]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=137</guid>
		<description><![CDATA[So now that I&#8217;ve got the Chumby it seemed like a good idea to test out creating and uploading my first widget.
This is my first foray into flash development, so for the moment I&#8217;m just cribbing from other sources.  I&#8217;m hoping that as Actionscript is a cousin of Javascript it won&#8217;t be too tricky [...]]]></description>
			<content:encoded><![CDATA[<p>So now that I&#8217;ve got the <a href='http://www.chumby.com/'>Chumby</a> it seemed like a good idea to test out creating and uploading my first widget.</p>
<p>This is my first foray into <a href='http://en.wikipedia.org/wiki/Adobe_Flash'>flash</a> development, so for the moment I&#8217;m just cribbing from other sources.  I&#8217;m hoping that as <a href='http://en.wikipedia.org/wiki/ActionScript'>Actionscript</a> is a cousin of <a href='http://en.wikipedia.org/wiki/JavaScript'>Javascript</a> it won&#8217;t be too tricky to pick up.  Though of course much of the learning will be related to the various APIs.</p>
<p>To get started I ran over to <a href='http://osflash.org/'>Open Source Flash</a> and read the article on <a href='http://osflash.org/projectsetup'>setting up a flash project without using the Flash IDE</a> (seeing as I don&#8217;t want to buy Flash - for now at least).  I then followed through from there to the <a href='http://www.mtasc.org/'>MTASC</a> site and looked at the example <a href='http://www.mtasc.org/#tutorial'>tutorial</a> and realised that may be all I needed to get a simple &#8220;Hello World&#8221; widget working.</p>
<p>So here&#8217;s the Actionscript I used (saved in <code>Tuto.as</code>):</p>
<pre><code>
class Tuto {

    static var app : Tuto;

    function Tuto() {
        _root.createTextField("tf",0,0,0,320,240);
        // write some text into it
        _root.tf.text = "Hello\nChumby!";

        // make the text appear bigger on the screen
        var format = new TextFormat();
        format.size = 64;
        _root.tf.setTextFormat(format);
    }

    // entry point
    static function main(mc) {
        app = new Tuto();
    }
}
</code></pre>
<p>Which is based on the code in the MTASC tutorial.</p>
<p>Then with MTASC downloaded and installed in <code>~/bin/mtasc-1.12-osx/</code> on my Powerbook, I compiled the code using:</p>
<pre><code>~/bin/mtasc-1.12-osx/mtasc -swf tuto.swf -main -header 320:240:12 Tuto.as</code></pre>
<p>Which creates the SWF file <code>tuto.swf</code>.</p>
<p>Note the <code>-header 320:240:12</code> option.  This is to set the size (320&#215;240) and framerate (12fps) of the resulting SWF.  These are the settings as required for the Chumby.</p>
<p>With that done I then tried out <code>tuto.swf</code> in my web-browser to make sure it worked.  Next I uploaded the widget via chumby.com (which meant I had to create an 80&#215;60 pixel icon too).  I made sure that the widget was set to private when uploading (seeing as only I wanted to see the widget) and then added it to my &#8220;development&#8221; channel.</p>
<p>Then I selected the &#8220;development&#8221; channel on my chumby to see the results:</p>
<p><center><img src="http://psychicorigami.com/wp-content/uploads/2008/05/img_5100.jpg" alt="" title="Hello Chumby!" width="480" height="388" class="alignnone size-full wp-image-138" /></center></p>
<p>I did run into a little trouble getting the widget to refresh after uploading.  It seemed to work sometimes, but in the end I <a href='http://wiki.chumby.com/mediawiki/index.php/Chumby_tricks#Hidden_screen_in_Control_Panel'>started sshd on the chumby</a> so I could stop and start the control panel (after connecting via ssh):</p>
<pre><code>
chumby:~# stop_control_panel
chumby:~# start_control_panel
</code></pre>
<p>Which seemed to solve the trick.  I&#8217;ll have to investigate other means of deploying to the chumby when I&#8217;m properly developing, but overall it wasn&#8217;t too much effort going via the chumby site.</p>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/05/29/hello-chumby-a-first-widget/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Unpacking Chumby</title>
		<link>http://psychicorigami.com/2008/05/28/unpacking-chumby/</link>
		<comments>http://psychicorigami.com/2008/05/28/unpacking-chumby/#comments</comments>
		<pubDate>Wed, 28 May 2008 19:56:21 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[chumby]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=135</guid>
		<description><![CDATA[So the Chumby finally arrived today.  Heather had very kindly and sneakily managed to arrange for it to be sent from the US (seeing as it&#8217;s not yet available over here in the UK) for my 30th.  I have to say that so far I&#8217;m pretty impressed.
It&#8217;s got that geek gadget factor working [...]]]></description>
			<content:encoded><![CDATA[<p>So the <a href='http://www.chumby.com/'>Chumby</a> finally arrived today.  Heather had very kindly and sneakily managed to arrange for it to be sent from the US (seeing as it&#8217;s not yet available over here in the UK) for my 30th.  I have to say that so far I&#8217;m pretty impressed.</p>
<p>It&#8217;s got that geek gadget factor working for it very well.  Lots of options to configure, but at the same time it&#8217;s pretty easy to use.  Lots more exploring to do, but even just the fact that it&#8217;ll play <a href='http://radioparadise.com/'>Radio Paradise</a> out of the box is enough for me&#8230;</p>
<p><center><br />
<a href="http://www.flickr.com/photos/lilspikey/2532030940/" title="IMG_5090 by lilspikey, on Flickr" onclick="javascript:urchinTracker ('/outbound/article/www.flickr.com');"><img src="http://farm4.static.flickr.com/3134/2532030940_87b9bb09b2.jpg" width="500" height="400" alt="IMG_5090" /></a></p>
<p><a href="http://www.flickr.com/photos/lilspikey/2532030168/" title="IMG_5093 by lilspikey, on Flickr" onclick="javascript:urchinTracker ('/outbound/article/www.flickr.com');"><img src="http://farm3.static.flickr.com/2030/2532030168_125937d92c.jpg" width="500" height="400" alt="IMG_5093" /></a></p>
<p><a href="http://www.flickr.com/photos/lilspikey/2532031210/" title="IMG_5097 by lilspikey, on Flickr" onclick="javascript:urchinTracker ('/outbound/article/www.flickr.com');"><img src="http://farm3.static.flickr.com/2290/2532031210_c155f52a01.jpg" width="500" height="400" alt="IMG_5097" /></a><br />
</center></p>
<p><a href='http://www.flickr.com/photos/lilspikey/tags/chumby/'>See more chumby photos</a></p>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/05/28/unpacking-chumby/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Muadib</title>
		<link>http://psychicorigami.com/2008/05/27/muadib/</link>
		<comments>http://psychicorigami.com/2008/05/27/muadib/#comments</comments>
		<pubDate>Tue, 27 May 2008 08:51:28 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[Artwork]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=133</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p><center><a href='http://psychicorigami.com/wp-content/uploads/2008/05/muadib.gif'><img src="http://psychicorigami.com/wp-content/uploads/2008/05/muadib-219x300.gif" alt="" title="muadib" width="219" height="300" class="alignnone size-medium wp-image-132" /></a></center></p>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/05/27/muadib/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Brush-pen mentats</title>
		<link>http://psychicorigami.com/2008/05/17/brush-pen-mentats/</link>
		<comments>http://psychicorigami.com/2008/05/17/brush-pen-mentats/#comments</comments>
		<pubDate>Sat, 17 May 2008 08:43:15 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[Artwork]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=130</guid>
		<description><![CDATA[I&#8217;d bought a brush pen quite some time ago, but hadn&#8217;t used it massively.  I&#8217;d found that I needed a waterproof ink for the kind of stuff I was doing (mostly inking the outline and painting with water-colour over the top).
Anyway, I thought I&#8217;d revisit the brush pen last night.  So I did a few [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;d bought a <a href="http://www.smokingspider.com/node/17" onclick="javascript:urchinTracker ('/outbound/article/www.smokingspider.com');">brush pen</a> quite some time ago, but hadn&#8217;t used it massively.  I&#8217;d found that I needed a waterproof ink for the kind of stuff I was doing (mostly inking the outline and painting with water-colour over the top).</p>
<p>Anyway, I thought I&#8217;d revisit the brush pen last night.  So I did a few sketches with it:</p>
<p><center><br />
<a href="http://psychicorigami.com/wp-content/uploads/2008/05/img_5037.jpg" ><img class="alignnone size-medium wp-image-131" title="brush pen mentats and sleeping girl" src="http://psychicorigami.com/wp-content/uploads/2008/05/img_5037-300x278.jpg" alt="" width="300" height="278" /></a><br />
</center></p>
<p>The sketches include the <a href="http://en.wikipedia.org/wiki/Mentat" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">mentats</a>, <a href="http://en.wikipedia.org/wiki/Piter_De_Vries" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">Piter de Vries</a> and <a href="http://en.wikipedia.org/wiki/Thufir_Hawat" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">Thufir Hawat</a>, as well as a certain girl sleeping.  Very pleasant working with the brush-pen, as it&#8217;s nice and quick and the results look quite striking.  Think I&#8217;ll be doing a few more of these.</p>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/05/17/brush-pen-mentats/feed/</wfw:commentRss>
		</item>
		<item>
		<title>MASS</title>
		<link>http://psychicorigami.com/2008/05/14/mass/</link>
		<comments>http://psychicorigami.com/2008/05/14/mass/#comments</comments>
		<pubDate>Wed, 14 May 2008 10:10:54 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[Open House]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=129</guid>
		<description><![CDATA[
Just a reminder that MASS is on for another two weekends (17th and 24th of May).  The preview video above should give you an idea of what to expect and even briefly features my piece in situ.
]]></description>
			<content:encoded><![CDATA[<p><center><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/bIkabAg3ANQ&#038;hl=en"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/bIkabAg3ANQ&#038;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></center></p>
<p>Just a reminder that <a href='http://www.shardcore.org/mass/'>MASS</a> is on for another two weekends (17th and 24th of May).  The preview video above should give you an idea of what to expect and even briefly features my piece in situ.</p>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/05/14/mass/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Java Psion Link - post-mortem</title>
		<link>http://psychicorigami.com/2008/05/05/java-psion-link-post-mortem/</link>
		<comments>http://psychicorigami.com/2008/05/05/java-psion-link-post-mortem/#comments</comments>
		<pubDate>Mon, 05 May 2008 10:38:47 +0000</pubDate>
		<dc:creator>john</dc:creator>
		
		<category><![CDATA[Development]]></category>

		<category><![CDATA[Java]]></category>

		<category><![CDATA[jpl]]></category>

		<category><![CDATA[psion]]></category>

		<guid isPermaLink="false">http://psychicorigami.com/?p=105</guid>
		<description><![CDATA[Quite some time ago I started a project to create a Java version of PsiWin.  This project was Java Psion Link.
A little background
PsiWin was the bit of software that Psion provided to communicate/sync/convert files between a regular PC and their (now defunct) PDAs - such as the 5mx, Revo and netBook.  You connected your [...]]]></description>
			<content:encoded><![CDATA[<p>Quite some time ago I started a project to create a Java version of <a href="http://www.garethjmsaunders.co.uk/psion/psiwin233_32.html" onclick="javascript:urchinTracker ('/outbound/article/www.garethjmsaunders.co.uk');">PsiWin</a>.  This project was <a href="http://littlespikeyland.com/psionlink/" onclick="javascript:urchinTracker ('/outbound/article/littlespikeyland.com');">Java Psion Link</a>.</p>
<h3>A little background</h3>
<p>PsiWin was the bit of software that <a href="http://www.psionteklogix.com/" onclick="javascript:urchinTracker ('/outbound/article/www.psionteklogix.com');">Psion</a> provided to communicate/sync/convert files between a regular PC and their (now defunct) PDAs - such as the <a href="http://en.wikipedia.org/wiki/Psion_5" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">5mx</a>, <a href="http://en.wikipedia.org/wiki/Psion_Revo" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">Revo</a> and <a href="http://en.wikipedia.org/wiki/NetBook" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">netBook</a>.  You connected your Psion to your PC with a serial connection (<a href="http://en.wikipedia.org/wiki/RS-232" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">RS232</a>) and could then treat the Psion like a disk on your PC.  You could navigate the Psion&#8217;s file system just like any disk and transfer files.  In addition you could use PsiWin to open and convert Psion&#8217;s native/custom files in normal Windows applications.</p>
<p>I myself owned a netBook and really enjoyed having it.  It was a really small laptop that I could carry around with me easily.  It even came travelling with me and had enough power to let me noodle around writing compilers and all sorts on the road.  In retrospect it was a bit pricey, but it was still a wonderful machine.  I&#8217;ve been eyeing up the <a href="http://eeepc.asus.com/global/" onclick="javascript:urchinTracker ('/outbound/article/eeepc.asus.com');">EEE PC</a> in the hope that it&#8217;ll make a good replacement for my netBook.  Though I&#8217;m probably going to wait for the bigger screened version to come out, as then it&#8217;ll at least have the same screen size.  Shame there won&#8217;t be a touch screen on it&#8230;</p>
<p style="text-align: center;"><a href="http://psychicorigami.com/wp-content/uploads/2008/04/images.jpg" ><img class="aligncenter size-medium wp-image-123" title="netBook" src="http://psychicorigami.com/wp-content/uploads/2008/04/images.jpg" alt="" width="132" height="136" /></a></p>
<p>There is still quite a thriving Psion community out there - well over five years since the last Psion rolled off of the production line.  People loved their Psions and rightly so.  These were fantastic machines, that unlike other &#8220;PDAs&#8221; were fully functioning computers and weren&#8217;t totally reliant on having a PC to act as a mothership.  In fact saying &#8220;people loved their Psions&#8221; is probably the wrong tense - people still love their Psions and continue to use them.   Even now I&#8217;ll still have the occasional mail about using JPL and looking at the <a href="http://sourceforge.net/project/stats/?group_id=70134&amp;ugn=javapsionlink" onclick="javascript:urchinTracker ('/outbound/article/sourceforge.net');">sourceforge site</a> shows people are still downloading it.</p>
<h3>Version 1.0</h3>
<p>So the one main problem I had was that I had an iMac, running MacOS 9 and PsiWin would only work on a PC.  This was around 2000.  There was a Mac version called <a href="http://www.amazon.co.uk/Macconnect-psion-series-5-software/dp/B00005JACP" onclick="javascript:urchinTracker ('/outbound/article/www.amazon.co.uk');">MacConnect</a>, but it only handled file transfer and came on a 3.5&#8243; disk.  My iMac didn&#8217;t have a 3.5&#8243; disk drive and didn&#8217;t feel like having to buy MacConnect (when PsiWin was free with the Psion) _and_ have to buy a USB disk drive.  So for quite a while I persevered with using the Comms app on the Psion to transfer files directly over a USB serial port adapter, as well as transferring files via compact flash (CF) disks.</p>
<p>Then I stumbled on some reversed engineered documentation for the &#8220;<a href="http://homepage.ntlworld.com/thouky/software/psifs/plp.html" onclick="javascript:urchinTracker ('/outbound/article/homepage.ntlworld.com');">Psion Link Protocol</a>&#8221; (PLP).  Without that documentation I would never have started writing JPL.  Even with this documentation it was quite a lot of hard work getting everything going.  I did finally get my head around hexadecimal notation.  Not bad for someone who&#8217;d done AI and no regular CS at uni.</p>
<p>Version 1.0 of JPL more or less worked, but was a bit flaky.  It&#8217;d crash and bring down the VM and sometimes even the mac itself!  It also suffered from being a bit of a hack job - I wrote enough to get it working, but didn&#8217;t really go back and rewrite things and refactor.</p>
<p>Still I put it online and had a few people downloading it and then started getting mail about it.  There&#8217;s a lot to be said for having people actually using your software - even if it is a bit flaky and needs some work!</p>
<p>However at about that point I took a year to go travelling in Australia, so development on JPL ground to a halt.  I did have the netBook in tow though and had got a java compiler working on it.  So with that and a gsm modem vaguely kept my eye on things.</p>
<h3>Version 2.0</h3>
<p>I started coding version 2 of JPL in a bar in <a href="http://en.wikipedia.org/wiki/Ko_Pha_Ngan" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">Ko Pha Ngan</a> on the netBook itself.  I couldn&#8217;t run the code of course, but I was able to get a lot of the structure down and compile the code.  In fact the code I wrote then still lived on, though greatly modified, into the version of JPL 2 I finally released.</p>
<p>I created myself an API for the Psion Link Protocol to code the GUI application against.  I was able to create input and output streams to write to individual files on the psion, so I could treat it like it&#8217;s own file system.  It took quite a bit of effort to make that happen, but it greatly simplified writing the overall application. I was effectively writing my own library for accessing the psion and also writing an application to use that library.</p>
<p>Of course I never quite achieved the level of separation I&#8217;d have liked.  In retrospect I wish I&#8217;d actually treated JPL as two projects.  I could have then released the library for other developers to use and then coded the GUI like I was a user of the library.  Hopefully this would have meant the core library would be quite small and focussed.</p>
<p>Another thing I wish I had done was to have actually made use of <a href="http://en.wikipedia.org/wiki/Unit_test" onclick="javascript:urchinTracker ('/outbound/article/en.wikipedia.org');">unit-testing</a> in JPL.  At the time I had no real experience of unit-testing, but since then have come to <a href="http://psychicorigami.com/2007/11/22/when-developing-in-your-spare-time-automated-tests-are-your-best-friend/" >realise how useful automated tests</a> can be.  It would of required a fair bit of thought in some places though.  Programming in Java would have required me to carefully consider how to mock-up a serial port and so on - no <a href="http://psychicorigami.com/2007/09/20/monkey-patching-pythons-smtp-lib-for-unit-testing/" >monkey patching</a> to get you out of jail in Java!</p>
<p>At the time though Java was a pretty good choice for me.  The language is receiving quite <a href="http://www.google.com/search?client=safari&amp;rls=en&amp;q=java+hate&amp;ie=UTF-8&amp;oe=UTF-8" onclick="javascript:urchinTracker ('/outbound/article/www.google.com');">a lot of flak</a> nowadays, but I&#8217;d spent two years previously chained to a C++ compiler.  Java by comparison was markedly more productive.  Plus it meant that I could get JPL running on the Mac, Windows and Linux.  The much vaunted &#8220;write once, run anywhere&#8221; paid off in my case.  Which is not to say I could just ignore platform differences, but it meant that the app was essentially functional on the three major platforms with little extra work.</p>
<p>As my main development platform was a mac I spent extra time exploiting some of the extra features of the mac&#8217;s java runtime (MRJ).  This meant that JPL was able to better act like a regular mac application.  By using <a href="http://java.sun.com/developer/technicalArticles/ALT/Reflection/" onclick="javascript:urchinTracker ('/outbound/article/java.sun.com');">java&#8217;s reflection api</a> I only had to create one version of the code.  JPL would detect whether certain classes were available and if so expose extra features to the user.</p>
<p> </p>
<h3>The real-world</h3>
<p>JPL was for the most part a hobby project.  I did get donated a Revo and a 5mx for testing and a little bit of funding at one point.  This helped get at least one more release of JPL out, but in the end the real-world got in the way.  In particular I started <a href="http://littlespikeyland.com/msc/" onclick="javascript:urchinTracker ('/outbound/article/littlespikeyland.com');">my MSc</a>.  Though I was able to spend some time working on JPL during this period I couldn&#8217;t really spend too long on it.  Taking out a career development loan to fund your further education does kind of sort out your priorities like that!</p>
<p>I also found that I was using my netBook less and less, so JPL itself was not as useful to me.  So like many open source projects, once I lost interest the incentive disappeared and work ground to a halt.  Which is not to say anything would have been different if I&#8217;d been running JPL as a commercial project.  I&#8217;m not sure there would have been enough users to have supported the cost of extra development.</p>
<p>Still it was an interesting project to have worked on.  It represented my first real &#8220;large&#8221; project outside of work and academia.  Since then I&#8217;ve always felt a need to have something I&#8217;m working on in my spare time.  Something to hone my skills with.  JPL was very useful for keeping my knowledge of Java up-to-date.  Now that I&#8217;m mostly coding in <a href="http://www.python.org/" onclick="javascript:urchinTracker ('/outbound/article/www.python.org');">Python</a> at home, having little <a href="http://chrss.co.uk/" onclick="javascript:urchinTracker ('/outbound/article/chrss.co.uk');">side-projects</a> is a great way to get some extra experience.  The trouble with most day-jobs of course being that you actually have clients and deadlines - so exploratory coding often goes out the window.</p>
<p>There&#8217;s nothing quite like trying to create something useful on your own time.  Writing software from beginning to end by yourself can give you insights that you might otherwise never get.  I&#8217;d thoroughly recommend it.</p>
]]></content:encoded>
			<wfw:commentRss>http://psychicorigami.com/2008/05/05/java-psion-link-post-mortem/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.141 seconds -->
<!-- Cached page served by WP-Cache -->
