An iPod hacker’s diary
I didn’t update CENSORED for quite a while, but during the last week, I finally took some time to push the project further. The result is version 0.2.0, available from SourceForge since yesterday night. The new version is all about artwork support: JPEG or PNG files that are placed next to music files will now be shown on playback. This sounds simple, but in fact, this little feature took me about half of the time I spent for the whole 0.1 series. Alas, this has only partly to do with the complex data structures Apple tends to use – a good share of the problems I had was generated by myself …
Tuesday: Basic Investigation
First, I have to say that CENSORED wouldn’t exist without the excellent work of the iPodLinux guys, because these people managed to create a quite comprehensive documentation about the iPod’s internal data formats. I used this reference for rebuild_db (and even contributed to it), I used it in CENSORED, and artwork support wouldn’t have worked without it, too. So the first thing to do when fiddling around with iPod control files is read this documentation.
The second thing to do is generate real-world example data. This means that I put the music files on my iPod out of the way (by »unfreezing« the iPod database, thus degrading the tracks to mere data files not recognized by the iPod or iTunes) to create a little »playground« for iTunes. I then copied one track with artwork to the iPod and compared the actual layout of the ArtworkDB file (the main controlling file for cover artwork) with the information from the iTunesDB documentation.
After some hours of work, I had code that produced a ArtworkDB the iPod accepted.
Wednesday: First images
One thing was strange, though. Normally, iTunes renders all the images into two files, F1027_1.ithmb
for the larger cover images and F1031_1.ithmb
for the smaller thumbnails. Since the file names were stored a zillion times all over the place in ArtworkDB, I assumed that these were arbitrary. So I used my own naming scheme to avoid clobbering iTunes-generated data. That didn’t work well – the iPod always showed empty images, even though the files existed and contained valid data.
It took me some hours to find out that the file names iTunes uses are not arbitrary, but obligatory – an iPod nano’s large artwork images must be stored in file 1027, and the small images are required to sit in 1031, even though every conceivable parameter of the images is stored explicitly in the ArtworkDB. I even managed to crash the iPod by interchanging the two files :)
Having resolved this problem, the next step was to generate actual image content. Up to that point, I just put dummy data files onto the iPod – if the device showed pixel noise, everything was OK, if it didn’t show anything or just white pixels, I assumed that something went wrong.
The images on iPods are all stored uncompressed in the display’s native pixel format, which is 16-bit little-endian RGB565 (i.e. looks like GBRG3553). I know this format from the graphics programming I do on the nano, so I wasn’t surprised. I quickly wrote the conversion code in Python (which happily turned out to execute much faster than I first thought) and tested it. Unfortunately, the image wasn’t correct. I got the typical artifacts that result from bad shifting of packed pixel formats – the shapes looked somewhat right, but there was something wrong about the colors. I debugged this for about one hour, and didn’t find a bug until I found out that there was indeed none – at least not in the place where I searched it: The shifting stuff was correct, I just got an index wrong. Argh.
Thursday: Partial Rewrite
The next step was to integrate the ArtworkDB code into the main CENSORED codebase. However, I noticed that the data model of the interface was far from useful for that purpose, so I spent that day with rearranging the code.
Friday: CENSORED Integration
With all the code in the right place, I finally integrated all the logic into CENSORED. (I’m still not completely happy with the interface, but at least it works.) The moment of truth came soon: I let CENSORED process all the tracks on my iPod. Of course, it didn’t work :) The iPod didn’t show artwork at all. After double-checking that the ArtworkDB was indeed correct (it was), I tested disabling multiple-instantiated images. These are images that are stored only once physically, but assigned to more than one track. This is the common case e.g. for album artwork. Strange enough, by reducing the instantiation count of every image to one (i.e. assigning album artwork to only one track of the album), everything worked smoothly.
Saturday: Making It Work
I concluded that the iPod didn’t like it if multiple images loaded their image data from the sample place. I absolutely didn’t understand why this was the case, but since it didn’t work otherwise, that had to be it. Since even iTunes put album artwork into the image files multiple times when I tested it, I was pretty sure that this was the problem, so I restructured my code again.
I was quite surprised that this didn’t work either – the iPod kept ignoring the ArtworkDB. Again, if I turned off multiple instantiation, everything was fine again. I was about to go mad, until I suddenly found out that there was that tiny little field in one of the list headers I stopped paying attention to after they were first implemented. This field is called »image count«, and I assigned it something like len(imagelist)
. The problem is that imagelist
isn’t a plain list if images. Instead it is a dictionary that maps each image’s file name to a list of songs that should display this image. A list of a list, so to speak. And consequently, after replacing the simple length calculation by sum(map(len, imagelist.values()))
, it finally worked. I could even return to real multiple instantiation (one physical image data record for all tracks that refer to one image).
The rest of the day was spent with building a image caching system similar to the existing track metadata cache, packaging the program for Windows via py2exe, updating the documentation, uploading everything and finally watching the third-place match of the World Cup …
Do you know a way to extract the cover images from the ArtworkDB on the iPod to a folder on my PC??
My external harddisk crashed so I had to reinstall all music on another harddisk, which went pretty well except for te Album Covers.
thx
Jeff: The Artwork isn’t stored on the iPod at the full resolution, only 100×100 (nano 1G-2G), 140×140 (photo), 200×200 (video) or 320×320 pixels (classic, nano 3G). They are stored uncompressed in byte-swapped RGB565 format in the F10xx_x.ithmb files.
hello
ok. i have STUPIDLY deleted the ‘artworkdb’ file from my ipod directory. Now obviously, my coverflow is empty. desolate.like a ghost town of album art. im talking 6000 tracks.
now my ipod is manually managed, and the artwork was manually saved to each album.
so, the artwork is still displayed on itunes. every album cover is STILL there, intact and being desplayed beautifully!
now.PLEASE tell me that there is a way i can somehow….RE-CREATE the ArtworkDB file from itunes?
BECAUSE, i copied an album cover displayed on itunes, then pasted it on to the whole album, and that one album cover is now displayed on my ipod. there must be a way of doing this on mass..do i really have to do this for every track now?
i couldn’t possibley do it manually…it would take forever…and the prospect of it is just…soul-destroyingly painful.
so please…anyone…
thanks for reading this
milkyjoe82: If you’re using rePear, it’s as simple as deleting the
/iPod_Control/Artwork/repear.artwork_cache
file. If you’re using iTunes, you shouldn’t ask me, because I don’t use it and thus don’t know if there’s any possibility for disaster recovery.