Richard Jones' Log

Tue, 27 Jun 2006
Shuttle HTPC ... continued

In my attempts to get the Shuttle HTPC working again, I tried the official "fix the product you sold me" channels. After contacting the retailer, Shuttle and finally the wholesaler, I got the message that the fan problem I'm having is "common" and that I'd need to ship the motherboard off to Taiwan to be fixed. The fix would cost me about $15-$20 (plus shipping) and would take about 6-8 weeks.

So I played around with the system fan, PSU, some wire and some resistors. I found that a serial resistance of about 55Ω got the fan running at a good speed (not too noisy). Unfortunately, it seemed to be drawing about 300mW or so, and at that power the little 1/4W resistors let out all their magic smoke.

So I bought a 5W 56Ω resistor ($0.48), soldered it in and the HTPC is now back up and running!

Mon, 26 Jun 2006
Pygame.draw challenge is over!

It was quite successful too! Download the submissions from the pygame.draw challenge.

Sadly I didn't find the time to finish my entry. I had planned on combos having bigger guns, and also for larger combos. Most of the code for both of those is done, so maybe I'll do some more work in the next week or so and see if I can get a more complete version out.

Sun, 25 Jun 2006
Pygame.draw challenge time limit extended

I'm not going to be awake at midnight, so that means that entrants in the pygame.draw challenge have a few extra hours to get their entries in.

Get entries to me by email before UTC (GMT) 23:59 Sunday 25th June.

category: Python | permanent link
Mon, 19 Jun 2006
Patterns in Python

Melbournians will recognise the pattern (I hope ;) For non-locals, the pattern adorns the external walls of Federation Square here in Melbourne. I think it's pretty cool :)

Code to generate it (requires pygame).

The pattern is called "Pinwheel Aperiodic Tiling" and is named for the pinwheel shape I've highlighted. Click the thumb for a full-size (well, 640x480 anyway) pattern.

Nokia 770 / pygame.draw playage

I've finally installed an ssh daemon on the 770* which makes developing on it much nicer (until I magically acquire a bluetooth keyboard and mouse - which I'm not even sure the device supports ;)

Anyway, I've run a few of the pygame.draw challenge entries on it (yes, I've had a couple already, woot) and the results have been interesting. Most run at quite a reasonable frame rate.

My entry, which I cap at 30FPS, runs about 26-29FPS. I have to work on the user input side of things - the little direction-pad doesn't really lend itself to games, unfortunately. We'll see...

One very CPU-intensive entry ran at 2FPS. It gets about 90-100FPS on my A64 3500+ desktop :)

Some gotchas for developing pygame on the 770:

  1. DON'T switch apps - you will lose the pygame window, requiring a shell "killall python2.4" (assuming no other python programs are running ;) )
  2. Related to point 1: make sure your app has a 770-compatible "exit" method (i.e. not the "escape" key like most games).
  3. PyGame is version 1.6 which is missing quite a few sprite features that are in 1.7.
  4. PyGame's default font is MIA. You will need your own font, which is a shame for the pygame.draw challenge.

*: I used the meta-package which includes osso-xterm, tiny-vim, slocate, openSSH and There's good install instructions on that page, but note that the install does require you enable root access.

category: Python | permanent link
Wed, 14 Jun 2006
Wiki in Django, anyone?

Has anyone got a wiki that I could plug into my existing Django installation? Minimum requirements:

  1. Obviously the basic wiki-linking, page creation, editing and removal,
  2. Page history with diffs and easy reversion of spam,
  3. Handling (upload / displaying) images, and
  4. "Login" for users to identify changes.

Nice to have:

  1. Control over cosmetics, and
  2. reStructuredText markup.

I'd use an existing wiki except my hosting has reached an "app" limit so I need to get it into my existing Django "app".

Tue, 13 Jun 2006
Python on a Nokia 770 (for effbot and Bob :)

So here's the skinny on playing with Python on a Nokia 770:

  1. Download and install python and x-term.
  2. Open an xterm, and run Python using "/var/lib/install/usr/bin/python2.4". Note that the TAB "key" works in ash, which saves a bunch of type-pecking.

I've yet to seriously investigate it, but this page has a lot of useful information.

I've recently installed FBReader and am reading some of Cory Doctorow's novels.

EDIT: fixed the python interpreter path. Sorry.

category: Python | permanent link
Pygame.draw challenge (PyWeek off-season challenge time)


Create a game in 64kbytes of source code using only pygame. No additional libraries, no external files (even ones loaded from a network). That means no PyOpenGL, no PNGs, no OGGs.


Start as soon as you read this announcement.

Human-readable, Linux-compatible entries must be received by before midnight on the 25th of June, 2006. That's Australian Eastern Standard Time, which is UTC +10.

Multiple entries are allowed. Teams are allowed. Monkeys are allowed! Ponies, sadly, are not allowed.


All entries will be posted to a page on the PyWeek website.

Entry gameplay instructions and license must be included in the source or in the game itself.

I will probably choose one of the entries as my favourite, and declare this in various obscure fora and private email messages. No other mention of rankings or favourites will be made.


Thanks to Phil Hassey for the challenge inspiration!

Sat, 10 Jun 2006
category: Python | permanent link
Fri, 09 Jun 2006
Shuttle HTPC woes, redux

The Shuttle PC I've had for a while now has recently taken another turn for the worse. Some readers may remember that a while back one of the fan controllers decided to stop working. To "fix" that I switched to the second fan controller. Now that one has stopped working too. Sometimes it gets stuck on "mid" speed (which is pretty noisy) and sometimes it just doesn't go at all.

In desperation, I pulled the case off and plugged the fan back into the primary fan controller. That worked (even controlling fan speed) for about a day until it cut off again. Switching back to the second controller has made it usable for another week (but stuck at the noisy "mid" speed).

I've now upgraded the BIOS to the latest version (even though the BIOS change notes mention nothing about fan control). No change.

I'm pretty annoyed at all this. Shuttles are not a cheap system. The rest of the components in the system are working fine - it's just that I can't keep it cool, even by forcing the fan to stay at a high speed.

I've done some poking around on the net and this isn't an isolated experience.

I'll definitely actively recommend against a Shuttle system to anyone I know in the future.

Next up I'm going to investigate hard-wiring in a potentiometer off of the power supply to manually control the fan speed.

Update: I've posted my "solution".

Thu, 08 Jun 2006
Random stuff

I just don't seem to find the time for "real" weblog entries these days, so here's some random stuff:

  • Pixen looks like a great tool for pixel art - certainly better than The Gimp for such things. Pity it's OS X-only.
  • I should nudge Phil Hassey about running that lightcycle Python bot comp.

And ObPython - because it's been a while - here's a very short little utility I just wrote on the train that fills my iRiver T10 (512MB capacity) with random music from my iTunes library using the ratings I assign in the library:

# usage: <export xml> <destination folder> <size>
# export xml is generated by iTunes' File > Export Library ...
# size may be in bytes or MB with a 'M' suffix
import urlparse, urllib, random, shutil, os, sys, cElementTree 

# command-line args
source_xml = sys.argv[1]
dest_folder = sys.argv[2]
assert os.path.isdir(dest_folder)
max_size = sys.argv[3]
if max_size[-1] == 'M': max_size = int(max_size[:-1]) * 1024 * 1024
else: max_size = int(max_size)

# parse the XML
library = cElementTree.ElementTree(file=source_xml)
sizes = {}
for track in library.getroot()[0].find('dict').findall('dict'):
    l = list(track)
    info = dict(zip([t.text for t in l[::2]], [t.text for t in l[1::2]]))
    if int(info.get('Rating', 0)) < 60:   # need 3+ stars
    track = urllib.unquote(urlparse.urlparse(info['Location'])[2])
    sizes[track] = int(info['Size'])

# shuffle
l = sizes.keys()

# fill
total_size = 0
for filename in l:
    size = sizes[filename]
    size += 512 - size%512  # 512 byte blocks
    total_size += size
    if total_size > max_size: break
    print '%3d%%'%(total_size * 100. / max_size), filename
    shutil.copy(filename, dest_folder)

The list comp / zip bit in the middle was kinda fun and I believe it constitutes the first time I've ever used a step slice argument, if you can believe that ;)