Present Perfect


Picture Gallery
Present Perfect

asynchronous task interface

Filed under: Hacking,Python — Thomas @ 23:13


In a previous post, I mentioned looking for some code implementing asynchronous operations that you can then attach a progress bar to.

I didn't end up finding anything, so as part of the ripping code I'm writing I prototyped a simple approach to it.

It's working nicely already; I have the basic class for a Task, a class for MultiTasks, and two runners - a command-line blocking one and a GtkProgressBar-using widget.

Here's the code if you're interested. You can run that file to see a simple DummyTask (one that takes 10 seconds to complete) progressing on the command line. Another example you can run (for which you need to check out the whole code) is examples/gtkchecksum.py which checksums decoded audio data using GStreamer and shows you a GTK+ progress bar. An even better example (but you'll need a complete CD rip with matching .cue file) is the ARcue.py program, which calculates AccurateRip checksums and compares them against the online database, and you can choose whether you want to run it in cli or gtk mode.

The cli one uses a GObject main loop to make the asynchronous code seem blocking again. I could easily add a Twisted reactor-using runner, but haven't needed it yet. Also, the one big annoyance I have with the otherwise excellent Twisted is the fact that you can't do much at all without the ugly 'global variable' that is the reactor.

I don't think I'm completely happy with these classes yet. I realized last week that unconsciously I was again moving towards an MVC approach with this, and realizing that also made me realize I'm not yet there. If you consider the Task the Model, then the Runner is currently both the View and Controller. I will probably need to split out the View part again, so I can attach multiple Views to the Model that is the task.

Also, I need to add a way to report on errors while executing the task, I'm considering adding timing statistics and finish estimation, and maybe something that allows doing global progress and subtask progress, the way ripping programs do too (showing current track percentage and complete disc percentage). Not sure how much I want to overengineer it though.

Feel free to comment, suggest improvements, or show me similar concepts and implementations!

Skype hack session

Filed under: GStreamer,Hacking,Python — Thomas @ 23:18


Today, Jan and I did some hacking over Skype! It was fun, worked out well. Jaime was off shopping and Kristien had her radio show and some interview with Flowrida.

Jan mostly helped me with stuff though, he didn't seem to need any help from me. I started ripping CD's to flac this week, and was very disappointed yesterday when my jukebox program didn't seem to work at all with .flac files. With Jan's help I narrowed down the problem, checked with Edward, then I fixed it on a git branch.

I also set up http publishing of my personal git branches, and a cgit installation. cgit was a little more difficult to configure than I'd like, the documentation isn't much help. I'll keep that for a separate post though.

Anyway, my jukebox is happily playing again with all the freshly and accurately ripped .flac files I have. My life just improved by 20% !

Although, I don't know whether it was switching to uridecodebin for decoding, or some bug in .flac, but sometimes the composition just seems to jump a few seconds.

I'll worry about that later, first fix some more bugs and make the jukebox example a bit more featureful. I'm wondering what to do on 'next' and 'previous' - rearrange the composition on the fly to match ? I hope gnonlin will be able to keep up...

Tip from our hacking session: add persistent history to your gdb session by putting the following in .gdbinit:

set history filename ~/.gdbhistory
set history save on


Filed under: Fun,Games,Spain — Thomas @ 21:53


I finally went out and bought Vin Diesel's Wheelman. It is set in Barcelona, awesome!

At least, some weird Frankenstein version of Barcelona. The map is a bit screwy, things are slightly out of place. I had read the game designers claimed they did so to make the game more dynamic, which is weird - Barcelona has one of the best city plans in the world, but these guys think they can do better than Ildefons Cerdà. So far it's just confusing.

The first mission didn't allow me to stray, but as soon as I dropped off the woman thief in Raval, I drove straight to work, to the World Trade Center. I wanted to drive underneath the hotel building, to the north building, up the stairs, and jump straight off the side, onto a ferry.

But they put FENCES in front of the World Trade Center!!! I can't get through!

I guess I'll have to take an actual plane and take the subway to work again on Monday...

Still, I already like the game. The effects are awesome, if comical. I already smashed 15 police cars into bits.

What is up with that casino just smack next to the World Trade Center though ? Hello ? It's not like it is that far to the two towers....


Filed under: Dave/Dina,Elisa,Hacking,Music — Thomas @ 19:29


Six years ago, before I moved to Barcelona, my digital music collection was well-organized and simple.

I had my CD's. And I had a copy of all of them, in Ogg, on my Dave/Dina box. I had very few downloaded tracks, and I didn't really listen to those much. All my music on Dave/Dina was tracked in DAD, a project I did with my former housemate Kristof.

Life was great. Every new CD was ripped directly in Dave/Dina, imported in DAD, and from there it could be rated. So each track was immediately available for the dynamic playlists DAD generated. Those playlists were then played directly on the Dave/Dina box attached to the living room stereo, my desktop, or the kitchen or bathroom computers (small Compaq IA1 machines from the Golden Bubble days).

Today, it's all a mess.

I have music (ripped, bought online, downloaded, or copied) on the following devices:

  • My elisa machine (which holds all the old Dave/Dina content)
  • My home desktop
  • My laptop
  • My work desktop
  • My Nokia N800
  • My Cowon A3 media player
  • Kristien's iPod

I haven't ripped a single CD in the last 4 years since I stopped working on Dave/Dina, so these days I also listen to CD's on either our small portable stereo or the PS3. I have 200+ CD's still waiting to be ripped.

So my music listening has become erratic, listening to either the old 'good' playlist from Dave/Dina that hasn't changed for the last 6 years, and, while good, is getting stale; or whatever I recently ended up downloading, for a specific album, but random play is terrible when going through those directories, and of course each album is on some different machine or device.

The last two years, I've grown more and more annoyed at this situation. So one of my goals for 2009 was to finally *do* something about it. I realize that music is one of the things I love most in life, and my life would be better with the music I buy and find in it as soon as I have it. So what little hacking time I have left before real life begins (you know, kids and stuff) is going to go in code that is going to make my music experience better.

Having goals is a good way to direct your hacking. I've come up with five major projects I need to work on to get my music where I want it to be. All of these are projects I've had thoughts on in the past, but never really gotten to. Over the last few years a lot of new ideas and technologies have arrived that would help a lot now however.

  1. Re-rip all my CD's in a lossless format, with perfect quality, according to a certain website's standard
  2. Find a replacement for DAD, or make one. It should be able to track rips, tracks, different encodings of the same recording, different versions of tracks, parts of tracks (hidden tracks for example), and different collections across devices that it should be able to synchronize. Think 'put 10 GB of the best songs on my N800', and each time I'd connect my N800 it would automatically add new ones and remove old ones.
  3. Improve on the rating system DAD used to have, reusing ideas from a project at the radio stations all those years ago. Have a bunch of fuzzy parameters on each track which would allow much richer controls for song selection. Possibly turn it into a collaborative website if it makes sense. This hinges on uniquely identifying each track, for which acoustic fingerprinting would be a good solution. Basically, I want to use the power of the web and the music lovers to improve song selection. last.fm and pandora are going in the right direction, but don't really satisfy me.
  4. Write a player that does the automatic mixing the way Dave/Dina used to, or better.
  5. Make a LEGO Mindstorms robot to automatically rip all my CD's again

I've been tackling each of these separately, which turned out to actually be a good thing. Each time I'm stuck on one of them, I can work on any of the others. For example, I've been stuck on (4) for a long time, waiting for Edward to fix some bugs in gnonlin, so I switched to (1), writing code to parse .CUE files, implement CDDB disc id calculation, and AccurateRip verification of ripped images.
I also waited on a friend who I worked with at said radio station to confirm that he doesn't have any backups either of the database for (3).

Since this is what I'll be hacking on in my spare time in the forseeable future, I'll probably blog about the different pieces as well. I'll start with some more technical information on (1), the ripping part, which I've been working on the last month, in a separate post.

But man, I look forward to ripping my CD's from the last four years and actually listening to those songs regularly, rather than once in a while.

Isn't it amazing how our parents actually had to get up from their desk, go over to the turntable, and actually flip an LP over if they wanted to hear something else for 20 minutes ?

Python’s struct.unpack

Filed under: Hacking,Python — Thomas @ 10:10


Is it just me, or does struct.unpack seem mostly useless to unpack any real-world binary data ? Real-world binary data usually has a fixed amount of bytes for each value to read out of a binary file. struct.unpack does not allow you to specify how many bytes to read for each value to unpack; rather, it has format specifiers that map to the C type declarations.

The only way I found that works to read, for example, sets of 32 bit signed integers, is to read them with one call per variable, and slicing the data, like so:

self.trackCount = struct.unpack("B", data[0])[0]
self.discId1 = "%08x" % struct.unpack("

Surely there's an obvious better way to do this ?

NOTE: for some reason WordPress does not allow me to have the first <L format string to show up as just that; instead it corrects it to '<I ' (different letter, and a space). FML.

« Previous PageNext Page »