OLPC as a music player

One side project I’ve been having fun with is creating an activity to allow the olpc to play music. At first I was just going to port a MusicPD (mpd) client over to olpc to allow me to use the laptop as a remote control at parties. Mpd runs as a system-level service that plays music, and then users can connect to it with many dozens of available clients to tell it to play music. It turned out that porting over a client was so easy that I decided to create a bundle that had its own mpd daemon builtin as well.

The client I chose is Sonata. I’ve used a lot of music players, including xmms, rhythmbox, amarok, banshee, and muine, but the combination of Sonata+mpd is the best way to enjoy music on Linux. It’s really, really good, and it’s worth the slight headache of setting up mpd.conf to get it working on your machine.

Sonata is also written in Python and only took maybe 20 lines of alteration to sugar-ize it. The author, Scott Horowitz, was even nice enough to incorporate my alterations into the main codebase, meaning that my bundle isn’t a fork of his project.

The bundle also contains a specially-compiled and configured version of the mpd daemon. And since I hate freedom, I’ve bundled an mp3 library along with it (But it also plays ogg). Music should be stored in /home/olpc/.mpd/Music, which could be symlinked to a mounted mmc device or USB key for greater storage. When the activity is started, the daemon is automagically started as well.

By default the client will connect to the olpc’s mpd daemon, but one can right-click on the main window and change the preferences to connect to any other mpd daemon on the network.

While I don’t know if this bundle will be useful to the kids, it’s useful to me and it shows the power of the bundle architecture. It really is plug and play 🙂

Sonata OLPC bundle (v7)

The Anti-Gadget

There’s an interesting article at raisethehammer.org that J5 linked to. It brings to mind some issues I’ve been thinking about ever since I started working on the XO, and moreso since Apple announced the iPhone.

The article ends this way:

When the Children’s Machine becomes available, one thought is that customers in the developed world could buy two machines, with one going to a child in the developing world. Buy one for the price of two, in other words.

If that happens, gadget lovers will have an interesting choice to make this year.

A lot of people have been salivating over the XO, and they are viewing it through the same lens as other products: as a gadget. I think this is a critical mistake, and by labelling the XO a “gadget” one loses sight of what the XO was designed for. If anything, I think the XO is the Anti-Gadget.

I would define a gadget as something Unuseless. It does appear to fill some need, and one can construct arguments in favor of purchasing it, but ultimately the purchase is discretionary.

I think a lot of people in the first-world see in the XO its gadget potential, like its dual-mode screen, mesh networking, or built-in camera. For most of us these features are unuseless — I never use my laptop in bright sun so I don’t need a dual-mode screen, I am always near an access point so I don’t need mesh networking, or I already have a digital camera.

But in the environment for which the olpc was designed these features are necessities. Without the dual-mode screen the laptop would be useless in outdoor classrooms. Without the mesh there would be no network infrastructure. The camera may be the first that many children have used and it may also be their first mirror. Every part of the laptop has been carefully chosen with these issues in mind.

If the XO was released to first-world consumers too soon I’m afraid that all context would be lost and it would be directly compared to the iPhone, the Nokia N800, or the latest tablet PC. Reviewers would apply their standard series of benchmarks and it would probably fail: it wouldn’t be able to play back HD video, it wouldn’t have a slick 3D desktop, and it surely wouldn’t synchronize their Office documents.

It’s important not to judge the XO by the standards of gadgets designed for the first world market. For once, wealthy Americans are not the target market for a new device. Instead, try to imagine a child for whom this is their new textbook, calculator, telephone, synthesizer, and newspaper. Although the XO may seem like a gadget, it’s not at all a gadget to the child who will be getting it.

Why RSS on a laptop for kids?

I’ve been happy to see some recent articles about the OLPC that mention PenguinTV, although not by name. The BBC and AP both mention the existence of an RSS reader, and both understandably felt it necessary to describe what that means:


The machine comes with a web browser, word processor and RSS reader, for accessing the web feeds that so many sites now offer.


A wide range of programs can run on it, including a Web browser, a word processor and an RSS reader — the software that delivers blog updates to information junkies.

I have a feeling that people reading these descriptions will wonder why the heck 5th graders would care about RSS feeds. While these are decent enough descriptions of what RSS is traditionally used for, it misses the point of why I worked to bring RSS to the olpc. When I was envisioning how the children would use PenguinTV, this is what I saw:

School Example 2

(Let me be clear here, this was my own personal hope and dream. It does not reflect the official position of olpc).

What’s important are not the specific images, subjects, and examples I’ve used, but how the data are presented. On the left is a list of subscribed feeds, representing classes the student is taking. On the right is a list of entries, of which there is one per class session. Each entry has associated notes and classroom materials. Every day this information would be automatically downloaded to the child’s laptop from the school server.

I think future students (if not current ones) will expect all classroom materials to be available online, whether from an internet server or a school server. I know I would have appreciated all my homework assignments as downloadable PDFs instead of crumplable, tearable, losable paper. Furthermore lectures for older kids could be recorded as audio or video and attached to the entry, meaning older students could catch up on missed classes. The storage of all these documents is managed directly by PenguinTV meaning that the student doesn’t need to know exactly where the files are stored on the hard drive.

So while RSS is known right now as a standard for “news junkies,” I hope that people can see how it can be used in other ways, including a classroom context.

With the introduction of The Journal, PenguinTV’s role has changed. The Journal will be a central part of the laptop experience and will keep track of all the user’s activities and files in an interface that may look similar to the screenshot above. This makes PenguinTV somewhat redundant for those uses. It still may have a role in retrieving data or as an offline web browser, but it’s probably not going to be the central class materials browser I envisioned.

Lately, it seems that my software has turned out to be a good testcase as a large software program with lots of dependencies. PenguinTV relies on Mozilla (to draw feeds), GStreamer (for audio and video playback), SQLite (for data storage), BitTorrent (for large files), and more. This makes it a great full-featured desktop program, but strains the laptop’s RAM capacity. (Right now most of the RAM is being used by mozilla, so improvements being made there are the most beneficial). Most of my work has been focused on improving PenguinTV so that it runs leaner and faster. If I can get it to perform well on the tiny laptop, not only will it be good for the children (should they become news junkies :)) but everyone running the desktop version as well.

I’m not at all disappointed to see the Journal doing what I imagined PenguinTV might do. After all, it must have been a good idea if someone else came up with it! The Journal is going to be one of the applications most often used by the children, so it needs to be much, much smaller than I could ever make PenguinTV. Because the Journal won’t be using html they won’t need mozilla, and they will probably use a more efficient storage mechanism than sqlite. Also PenguinTV does not work well with many entries in one feed, whereas the Journal will need to work for years-worth of data. So while it won’t be my own software, the kids will be getting the computer I wish had been available to me when I was in school. Lucky punks!

PenguinTV database accesses: more optimal than ever!

I’ve been working to push database accesses down further on PenguinTV to lessen the load it puts on the disk. If the system is under heavy disk load to begin with, PenguinTV slows to a crawl and becomes unusable. Following up on my previous optimization work, a database hit for an unread entry is now this:

SELECT title, creator, link, description, feed_id, date, read FROM entries WHERE id=? (93729,)
SELECT id,entry_id,url,file,download_status,viewed,length,mimetype FROM media WHERE entry_id = ? (93729,)
UPDATE entries SET read=? WHERE id=? (1, 93729)
UPDATE media SET viewed=? WHERE entry_id=? (1, 93729)
SELECT id FROM feeds WHERE feed_pointer=? (322,)

We only read from each table once, and only write to each table once. That’s about as good as it can get, I think.

Adventures in virtualization

I’ve been adapting PenguinTV for use on the olpc, which is not entirely easy. For an all-python application it’s not too hard, but I have precompiled libraries that I need to distribute with PenguinTV because the olpc doesn’t provide pycurl. Since I run Ubuntu Edgy and the olpc is based on Fedora Core 6, I need to do some sort of virtualization to test my activity.

The recommended practice is to download an OLPC OS Image and run it with qemu. Unfortunately, the image is broken for Debian-based distributions like mine.

The next option is to download the OS image and chroot inside it and run sugar-emulator from there. That also doesn’t work for me.

My solution is really complicated: Run Fedora Core 6 in VMWare, and then chroot inside the OS image from there. Success!

So here’s a picture of PenguinTV, running inside olpc build 142, chrooted on FC6, running inside VMWare Workstation, on Ubuntu. It’s not a pretty way to do software development, but it seems to work.


PenguinTV optimization

I’ve been going through the crufty and scary ptvDB.py looking for ways to improve performance. Armed with the trust profile and pstats modules, I cut polling time in half by removing redundant and unnecessary database hits.

I then got the idea of generating a print statement every time I hit the DB, so I can see exactly what the database is doing during regular operation.

The result is not always pretty:

Basic article read:

SELECT title, creator, link, description, feed_id, date FROM entries WHERE id=? (69443,) ok
SELECT id,entry_id,url,file,download_status,viewed,length,mimetype FROM media WHERE entry_id = ? (69443,) ok
SELECT read FROM entries WHERE id=? (69443,) ok

Ok that’s fine, we get the entry, any associated media, and then the read state.

What about an unread entry?
SELECT title, creator, link, description, feed_id, date FROM entries WHERE id=? (67523,) ok
SELECT id,entry_id,url,file,download_status,viewed,length,mimetype FROM media WHERE entry_id = ? (67523,) ok
SELECT read FROM entries WHERE id=? (67523,) ok
UPDATE entries SET read=? WHERE id=? (1, 67523) ok
UPDATE media SET viewed=? WHERE entry_id=? (1, 67523) ok
SELECT read FROM entries WHERE id=? (67523,) ok
SELECT id,entry_id,url,file,download_status,viewed,length,mimetype FROM media WHERE entry_id = ? (67523,) ok
SELECT title, creator, link, description, feed_id, date FROM entries WHERE id=? (67523,) ok
SELECT id,entry_id,url,file,download_status,viewed,length,mimetype FROM media WHERE entry_id = ? (67523,) ok
SELECT read FROM entries WHERE id=? (67523,) ok
SELECT feed_pointer,description FROM feeds WHERE id=? (233,) ok
SELECT id,title,fakedate FROM entries WHERE feed_id=? ORDER BY fakedate DESC (233,) ok
SELECT id FROM entries WHERE feed_id=? (233,) ok
SELECT feed_pointer FROM feeds WHERE id=? (233,) ok
SELECT pollfail FROM feeds WHERE id=? (233,) ok
SELECT feed_pointer FROM feeds WHERE id=? (233,) ok
SELECT read FROM entries WHERE feed_id=? (233,) ok
SELECT id FROM feeds WHERE feed_pointer=? (233,) ok

Oops. It’s whacking the database three times for the entry data, and updates the whole feed as well. Time to figure out what I’m doing wrong!