Sunday, December 30, 2007

Tablet Python #2 - Resource Modules

Introduction

In this second episode of Tablet Python, I'm going to tell you about an easy way to make resource modules. A resource module is a Python module which you can import for loading resources such as images, fonts, or whatever you want.

For example:

import graphics

img = gtk.Image()
img.set_from_pixbuf(graphics.icon)


Implementation

In episode #1 we talked about writing relocatable software. We are going to apply the same technique for resource modules, since they will be relocatable as well.

Our resource modules are Python packages, i.e. a subdirectory with a __init__.py file in it. The name of the directory will be the module's name. Be careful to only use valid characters (characters valid for Python variables) in the directory name and the filenames of the resource files (e.g., my_icon.png is OK, while my-icon.png would be not!).

Let's assume the following filesystem structure for our example:

graphics/
+ __init__.py
+ icon.png
+ logo.png
+ background.png

test.py

The package directory will also contain the resource files. In order to access them, we'll have to put them into the module namespace. Write the following into graphics/__init__.py:

import os
import gtk

_RESOURCE_PATH = os.path.dirname(__file__)

def _load_resources():

# Find all .png files in the resource directory. This construct is called
# "list comprehension" and will be covered in detail in episode #3.
# This returns a list of the names of all files in the resource directory
# ending with ".png".
resources = [ f for f in os.listdir(_RESOURCE_PATH)
if f.endswith(".png") ]

# load resources into module namespace
for r in resources:

# the filename without extension will be the name to access the
# resource, so we strip off the extension
name = os.path.splitext(r)[0]

# this is the full path to the resource file
path = os.path.join(_RESOURCE_PATH, r)

# Now we can load the resource into the module namespace.
# globals() gives us the dictionary of the module-global variables,
# and we can easily extend it by assigning new keys.
globals()[name] = gtk.gdk.pixbuf_new_from_file(path)

#end for

# load the resources when importing the module
_load_resources()

That's all. Let's test it with a tiny test program test.py:

import gtk
import graphics

win = gtk.Window(gtk.WINDOW_TOPLEVEL)
img = gtk.Image()
img.set_from_pixbuf(graphics.logo)
win.add(img)
win.show_all()

gtk.main()

You may put as many resource files as you want into the resource directory and simply access them by their name. The files are loaded only once when the module gets imported the first time. Subsequent import statements reuse the module without reloading the resources. I'm going to talk about the "singleton" nature of Python modules in a later episode.

A more sophisticated example of resource modules can be found in the theming engine of MediaBox (the subdirectory called theme).

Monday, December 24, 2007

MediaBox doesn't like winter?

There crawled a stupid little bug into MediaBox which made it dislike winter. A bug in the clock module made it return bogus data during winter. Since winter started recently, MediaBox failed to start up after December 22nd.

clock

The new release 0.92.1 fixes this. Now you can enjoy MediaBox again!


Merry Christmas!

Monday, December 17, 2007

MediaBox with Internet Radio

Now you can listen to internet radio stations (MP3, Ogg, AAC, etc; realaudio not supported) with the MediaBox Media Center.

The new release also features fullscreen song information.
MediaBox Song Info

The package installs on OS 2007, OS 2008, and even OS 2006. Not all features are enabled on OS 2006 at the moment, though.

Have fun and don't hesitate to report any bugs.

Tuesday, December 11, 2007

Important Bugfix for MediaBox

I have just released MediaBox 0.91.1 to fix a critical bug in 0.91. If you're using MediaBox 0.91 with FM radio you should upgrade!

MediaBox 0.91 has a bug which can break the radio stations list in the FM radio applet. After the list is broken, MediaBox will hang during startup. The new release fixes this.

Sunday, December 9, 2007

MediaBox gets FM radio

I have been busy getting FM radio in the MediaBox media center ready for release. So if you have a N800 (the only Nokia internet tablet with built-in FM tuner chip so far), you will get the radio button at the bottom.

FM radio in action

But the new release will also bring some improvements to N810 users (sorry, no FM radio on the N810...). Kinetic scrolling is now smoother without the occasional "hiccups" while playing an audio file. Some bugs have been squashed as well.

Oh, and since MediaBox uses pyFMRadio for the FM radio, I made a new release of this as well. The new version has improved signal scanning for automatic station detection.

Saturday, December 1, 2007

Tablet Python #1 - Relocatable Software

Python is becoming more and more popular for development on the Nokia internet tablets. It is indeed a very powerful and clear language and makes it easy to write applications that work on all internet tablet versions.

With this post I'm starting a new series on nice Python tricks which might be interesting to tablet software developers. So, if you're doing something in Python on your tablet, this series is for you!

In this first episode I will talk about writing relocatable software. This is software which works no matter where it's installed. There are no hardwired absolute paths to resources in relocatable software.

Knowing where you are

Every Python module knows the path where it's installed. You can retrieve the module's path by reading the __file__ variable.

print "This module resides at:", __file__

This makes it easy to find the directory where your app is installed:

import os
path = os.path.dirname(__file__)


Finding your resources

So if you want to load bundled resources into your application, you know where to find them:

path = os.path.dirname(__file__)
image_file = os.path.join(path, "images", "foo.png")
img = gtk.Image()
img.set_from_file(image_file)


Starting the application

This is the way I use to make my programs executable on the tablet. All of the program files and resources are within a subdirectory (e.g. /usr/lib/myapp/) together with the executable start module, which could look like this:

#! /usr/bin/env python

from mediabox.App import App

app = App()
app.run()

Let's assume this file is /usr/lib/mediabox/MediaBox. Then I make a symbolic link to this file as /usr/bin/MediaBox, and it's all done.

If I move my software to another place, I would just have to update this link.