ITunesDB/iTunesDB File
From wikiPodLinux
iTunesDB file
The iTunesDB file consists of a sort of tree structure arranged into a flat file. Each "object" contains a header followed by some other objects. The header contains a couple of size fields that are used to define where the header ends and other objects begin. Here's the basic structure of it:
<mhbd> - This is a database <mhsd> - This is a list holder, which holds either a mhla <mhla> - This holds a list of albums <mhia> - This describes a particular Album Item <mhod> - These hold strings associated with an album title <mhod> - These hold strings associated with an artist name/title <mhia> - This is another album. And so on. <mhod>... <mhod>... ... <mhsd> - This is a list holder, which holds either a mhlt or an mhlp <mhlt> - This holds a list of all the songs on the iPod <mhit> - This describes a particular song <mhod>... - These hold strings associated with a song <mhod>... - Things like Artist, Song Title, Album, etc. <mhit> - This is another song. And so on. <mhod>... <mhod>... ... <mhsd> - Here's the list holder again.. This time, it's holding an mhlp <mhlp> - This holds a bunch of playlists. In fact, all the playlists. <mhyp> - This is a playlist. <mhod>... - These mhods hold info about the playlists like the name of the list. <mhip>... - This mhip holds a reference to a particular song on the iPod. ... <mhyp> - This is another playlist. And so on. <mhod>... - Note that the mhods also hold other things for smart playlists <mhip>... ... ...
And so on. What follows is a detailed description of these various headers.
Chunk Encoding
Each chunk of the file is encoded in the follow form:
Offset | Field | Size | Description |
---|---|---|---|
0 | Chunk Type Identifier | 4 | A 4-byte string like "mhbd", "mhlt", etc. This identifies what type of chunk is at the current location. |
4 | End of Type-specific Header | 4 | This is a little-endian encoded 32b value that points to the end of the chunk-specific header. |
8 | End of Chunk or Number of Children | 4 | This is a little-endian encoded 32b value. It either points to the end of the current chunk, or the number of children the current chunk has. |
The Chunk Type Identifier is intuitive: it's a 4-byte string letting you know what you're working with.
The End of Type-specific Header tells you where, relative to offset 0, the header section for this chunk ends. The header starts at offset 12 and runs through to the end of the type-specific header.
The End of Chunk or Number of Children is slightly confusing. Usually, it's an "End of Chunk" offset: what the last offset in the current chunk is. That is, it tells you how long this chunk and all its children are. There are two big exceptions to this: "mhlt" and "mhlp" chunks. In both of these, this number is how many top-level children the mhl[pt] chunk has.
Database Object
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhbd |
4 | header length | 4 | size of the mhbd header. For dbversion <= 0x15 (iTunes 7.2 and earlier), the length is 0x68. For dbversion >= 0x17 (iTunes 7.3 and later), the size is 0xBC. |
8 | total length | 4 | size of the header and all child records (since everything is a child of MHBD, this will always be the size of the entire file) |
12 | unknown | 4 | always seems to be 1 |
16 | version number | 4 | appears to be a version number of the database type. 0x09 = iTunes 4.2, 0x0a = iTunes 4.5, 0x0b = iTunes 4.7, 0x0c = iTunes 4.71/4.8, 0x0d = iTunes 4.9, 0x0e = iTunes 5, 0x0f = iTunes 6, 0x10 = iTunes 6.0.1(?), 0x11 = iTunes 6.0.2-6.0.4, 0x12 = iTunes 6.0.5., 0x13 = iTunes 7.0, 0x14 = iTunes 7.1, 0x15 = iTunes 7.2, 0x16 = ?, 0x17 = iTunes 7.3.0, 0x18 = iTunes 7.3.1-7.3.2., 0x19 = iTunes 7.4, 0x1A = iTunes 7.5. |
20 | number of children | 4 | the number of MHSD children. This has been observed to be 2 (iTunes 4.8 and earlier) or 3 (iTunes 4.9 and older), the third being the separate podcast library in iTunes 4.9. Also it has been observed to be 4 (iTunes 7.1, 7.2) or 5 (iTunes 7.3). |
24 | id | 8 | appears to a 64 bit id value for this database. Not checked by the iPod, as far as I can tell. |
32 | unknown | 2 | always seems to be 2 |
38 | unknown | 8 | Observed in dbversion 0x11 and later. It was thought that this field is used to store some sort of starting point to generate the item's dbid, but this idea was thrown away. |
48 | unknown | 2 | Observed in dbversion 0x19 and later, and must be set to 0x01 for the new iPod Nano 3G (video) and iPod Classics. The obscure hash at offset 88 needs to be set as well. |
50 | unknown | 20 | Observed in dbversion 0x19 and later for the new iPod Nano 3G (video) and iPod Classics. Meaning unknown so far. |
70 | language | 2 | Observed in dbversion 0x13. It looks like this is a language id (langauge of the iTunes interface). For example for English(United States) this field has values 0x65 and 0x6E which is 'en'. The size of the filed might be bigger to distinguish different 'flavors' of a language. |
72 | library persistent id | 8 | Observed in dbversion 0x14. This is a 64-bit Persistent ID for this iPod Library. This matches the value of "Library Persistent ID" seen in hex form (as a 16-char hex string) in the drag object XML when dragging a song from an iPod in iTunes. |
88 | obscure hash | 20 | Observed in dbversion 0x19 for iPod Nano 3G (video) and iPod Classics. |
rest of header is zero padded |
The Database Object has two or three children, which are Data Sets.
DataSet
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhsd |
4 | header length | 4 | size of the mhsd header |
8 | total length | 4 | size of the header and all child records |
12 | type | 4 | A type number.
1 = Track list - contains an MHLT 2 = Playlist List - contains an MHLP 3 = Podcast List - optional, probably. Contains an MHLP also. This MHLP is basically the same as the full playlist section, except it contains the podcasts in a slightly different way. See the Playlists section. 4 = Album List, first seen with iTunes 7.1. 5 = New Playlist List with Smart Playlists, first seen with iTunes 7.3. |
rest of header is zero padded |
Depending on the type of Data Set, it will contain either a Track List child or a Playlist List child. Order is not guaranteed. Example files have contained the type 3 MHSD before the type 2 MHSD. In order for the iPod to list podcasts the type 3 Data Set MUST come between the type 1 and type 2 Data Sets.
TrackList
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhlt |
4 | header length | 4 | size of the mhlt header |
8 | number of songs | 4 | the total number of songs in the Track List |
rest of header is zero padded |
The Track List has Track Items as its children. The number of Track Items is the same as the number of songs.
Track Item
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhit |
4 | header length | 4 | size of the mhit header. For dbversion <= 0x0b (iTunes 4.7 and earlier), the length is 0x9c. For dbversion >= 0x0c (iTunes 4.71 and later), the size is 0xf4. For dbversion = 0x12 (iTunes 6.0.5), 0x13 (iTunes 7.0) the size is 0x148. For dbversion >= 0x14 (iTunes 7.1) the size is 0x184. |
8 | total length | 4 | size of the header and all child records |
12 | number of strings | 4 | number of strings (mhods) that are children of this mhit |
16 | unique id | 4 | unique ID for a track (referenced in playlists) |
20 | visible | 4 | If this value is 1, the song is visible on the iPod. All other values cause the file to be hidden. Was previously known as unk1. |
24 | filetype | 4 | This appears to always be 0 on 1st through 4th generation hard drive-based iPods. For the iTunesDB that is written to the 5th generation iPod (iPod Video) and the iPod Shuffle, iTunes 4.7.1 (and greater) writes out the file's type as an ANSI string padded with spaces. For example, an MP3 file has a filetype of 0x4d503320 -> 0x4d = 'M', 0x50 = 'P', 0x33 = '3', 0x20 = <space>. AAC is 0x41414320 & "new" AAC which is used by iTunes 7, M4A, is 0x4D344120. Protected AAC files (purchased from iTunes Store) are M4P = 0x4D345020. Was previously known as unk2. This really is an integer field and is reversed in iTunesDB used in mobile phones with reversed endianess. |
28 | type1 | 1 | CBR MP3s are type 0x00, VBR MP3s are type 0x01, AAC are type 0x00 |
29 | type2 | 1 | CBR MP3s are type 0x01, VBR MP3s are type 0x01, AAC are type 0x00 (type1 and type2 used to be one 2 byte field, but by it doesn't get reversed in the reversed endian iTunesDB for mobile phones, so it must be two fields). |
30 | compilation flag | 1 | 1 if the flag is on, 0 if the flag is off |
31 | stars/rating | 1 | the rating of the track * 20. Note that the iPod does not update this value here when you change the rating. See the Play Counts file for more information. |
32 | last modified time | 4 | last modified time of the track |
36 | size | 4 | size of the track, in bytes |
40 | length | 4 | length of the track, in milliseconds |
44 | track number | 4 | the track number of the track (the 9 in 9/15) |
48 | total tracks | 4 | the total number of tracks on this album (the 15 in 9/15) |
52 | year | 4 | year of the track |
56 | bitrate | 4 | bitrate of the track (ie, 128, 320, etc) |
60 | sample rate | 4 | sample rate of the track (ie. 44100) multiplied by 0x10000. |
64 | volume | 4 | Volume adjustment field. This is a value from -255 to 255 that will be applied to the track on playback. If you adjust the volume slider in iTunes track info screen, this is what you are adjusting. |
68 | start time | 4 | time, in milliseconds, that the song will start playing at |
72 | stop time | 4 | time, in milliseconds, that the song will stop playing at |
76 | soundcheck | 4 | The SoundCheck value to apply to the song, when SoundCheck is switched on in the iPod settings. The value to put in this field can be determined by the equation: X = 1000 * 10 ^ (-.1 * Y) where Y is the adjustment value in dB and X is the value that goes into the SoundCheck field. The value 0 is special, the equation is not used and it is treated as "no Soundcheck" (basically the same as the value 1000). This equation works perfectly well with ReplayGain derived data instead of the iTunes SoundCheck derived information. |
80 | play count | 4 | play count of the song. Note that the iPod does not update this value here. See the Play Counts file for more information. |
84 | play count 2 | 4 | Also stores the play count of the song. Don't know if it ever differs from the above value. |
88 | last played time | 4 | time the song was last played. Note that the iPod does not update this value here. See the Play Counts file for more information. |
92 | disc number | 4 | disc number, for multi disc sets |
96 | total discs | 4 | total number of discs, for multi disc sets. |
100 | userid | 4 | Apple Store/Audible User ID (for DRM'ed files only, set to 0 otherwise). Previously known as unk5. |
104 | date added | 4 | date added to the iPod or iTunes (not certain which) |
108 | bookmark time | 4 | the point, in milliseconds, that the track will start playing back at. This is used for AudioBook filetypes (.AA and .M4B) based on the file extension. Note that there is also a bookmark value in the play counts file that will be set by the iPod and can be used instead of this value. See the Play Counts file for more information. |
112 | dbid | 8 | Unique 64 bit value that identifies this song across the databases on the iPod. For example, this id joins an iTunesDB mhit with a ArtworkDB mhii. iTunes appears to randomly create this value for a newly formatted iPod, then increments it by 1 for each additional song added. Previously known as unk7 and unk8. |
120 | checked | 1 | 0 if the track is checked, 1 if it is not (in iTunes) |
121 | application rating | 1 | This is the rating that the song had before it was last changed, sorta. If you sync iTunes and the iPod, and they have different (new) ratings, the rating from iTunes will go here and the iPod rating will take precedence and go into the normal rating field. I'm uncertain what exactly this is for, but it's always set to what the iTunes rating is before each sync. |
122 | BPM | 2 | the BPM of the track |
124 | artwork count | 2 | The number of album artwork items put into the tags of this song. Even if you don't put any artwork items into the tags of the song, this value must at least be 1 for the iPod to display any artwork stored in the ithmb files. |
126 | unk9 | 2 | unknown, but always seems to be 0xffff for MP3/AAC songs, 0x0 for uncompressed songs (like WAVE format), 0x1 for Audible |
128 | artwork size | 4 | The total size of artwork (in bytes) attached to this song (i.e. put into the song as tags). Observed in iPodDB version 0x0b and with an iPod Photo as well as with iPodDB version 0x0d and an iPod Nano. |
132 | unk11 | 4 | unknown |
136 | sample rate 2 | 4 | The sample rate of the song expressed as an IEEE 32 bit floating point number. It's uncertain why this is here. |
140 | date released | 4 | date/time added to music store? For podcasts this corresponds to the release date as displayed to the right of the podcast title. Formerly known as unk13. |
144 | unk14/1 | 2 | unknown, but MPEG-1 Layer-3 songs appear to be always 0x000c, MPEG-2 Layer 3 songs (extrem low bitrate) appear to be 0x0016, MPEG-2.5 Layer 3 songs are 0x0020, AAC songs are always 0x0033, Audible files are 0x0029, WAV files are 0x0000. |
146 | unk14/2 | 2 | probably 1 if played on or more times in iTunes and 0 otherwise (at least for MP3 -- the value has been observed to be always 1 for AAC and Audible files, and always 0 for WAV files?) |
148 | unk15 | 4 | unknown - used for Apple Store DRM songs (always 0x01010100?), zero otherwise |
152 | unk16 | 4 | unknown |
156 | Skip Count | 4 | Number of times the track has been skipped. Formerly unknown 17 (added in dbversion 0x0c) |
160 | Last Skipped | 4 | Date/time last skipped. Formerly unknown 18 (added in dbversion 0x0c) |
164 | has_artwork | 1 | added in dbversion 0xd. Seems to be set to 0x02 for tracks without associated artwork (even if artwork is present, it will not be shown on the iPod) and 0x01 for tracks with associated artwork. |
165 | skip_when_shuffling | 1 | sets "Skip When Shuffling" when set to 0x1 (added in dbversion 0xd, formerly known as flag2) |
166 | remember_playback_position | 1 | sets "Remember Playback Position" when set to 0x1 (added in dbversion 0xd). Note that Protected AAC files (.m4b extension) and Audible files (.aa extension) do not set this flag or the previous one (skip_when_shuffling), and yet are always bookmarkable and are never included in the song shuffle. To determine if a file is bookmarkable, therefore, check the file type first. If it's not an .m4b or .aa, then check this flag in iTunesDB. (Formerly known as flag3) |
167 | flag4 | 1 | some kind of "Podcast" flag (added in dbversion 0xd)? When this flag is set to 0x1 then the "Now playing" page will not show the artist name, but only title and album. When additionally has_artwork is 0x2 then there will be a new sub-page on the "Now playing" page with information about the podcast/song.
If the track item is a kind of podcast then this flag must be set to 0x1 or 0x2, otherwise this flag must be set to 0x0. If this flag do not follow this, it might be removed from iTunesDB when user change there iPod to sync podcasts/songs in iTunes. |
168 | dbid2 | 8 | Until dbversion 0x12, same data as dbid above (added in dbversion 0x0c). Since 0x12, this field value differs from the dbid one. |
176 | lyrics flag | 1 | set to 0x01 if lyrics are stored in the MP3 tags ("USLT"), 0 otherwise. |
177 | movie file flag | 1 | if 0x1, it is a movie file. Otherwise, it is an audio file. |
178 | played_mark | 1 | added in dbversion 0x0c, first values observed in 0x0d. Observed to be 0x01 for non-podcasts. With podcasts, a value of 0x02 marks this track with a bullet as 'not played' on the iPod, irrespective of the value of play count above. A value of 0x01 removes the bullet. Formerly known as unk20. |
179 | unk17 | 1 | unknown - added in dbversion 0x0c. So far always 0. |
180 | unk21 | 4 | unknown (added in dbversion 0x0c) |
184 | pregap | 4 | Number of samples of silence before the songs starts (for gapless playback). |
188 | sample count | 8 | Number of samples in the song (for gapless playback). |
196 | unk25 | 4 | unknown (added in dbversion 0x0c) |
200 | postgap | 4 | Number of samples of silence at the end of the song (for gapless playback). |
204 | unk27 | 4 | unknown - added in dbversion 0x0c, first values observed in 0x0d. Appears to be 0x1 for files encoded using the MP3 encoder, 0x0 otherwise. |
208 | Media Type | 4 | (formerly known as unk28; added in dbversion 0x0c). It seems that this field denotes the type of the file on (e.g.) the 5g video iPod. It must be set to 0x00000001 for audio files, and set to 0x00000002 for video files. If set to 0x00, the files show up in both, the audio menus ("Songs", "Artists", etc.) and the video menus ("Movies", "Music Videos", etc.). It appears to be set to 0x20 for music videos, and if set to 0x60 the file shows up in "TV Shows" rather than "Movies". The following list summarizes all observed types:
Caution: Even if a track is marked as "Audiobook" here (value 0x08), it will not show up in the "Audiobooks" menu on the iPod. Only *.aa and *.m4b are shown there by recent firmwares. One proven exception: On the nano they show if they have the correct media type set here and the MHIT also has a chapter data mhod! |
212 | season number | 4 | the season number of the track, for TV shows only. Previously known as unk29. (added in dbversion 0x0c) |
216 | episode number | 4 | the episode number of the track, for TV shows only - although not displayed on the iPod, the episodes are sorted by episode number. Previously known as unk30. (added in dbversion 0x0c) |
220 | unk31 | 4 | unknown (added in dbversion 0x0c). Has something to do with protected files - set to 0x0 for non-protected files. |
224 | unk32 | 4 | unknown (added in dbversion 0x0c) |
228 | unk33 | 4 | unknown (added in dbversion 0x0c) |
232 | unk34 | 4 | unknown (added in dbversion 0x0c) |
236 | unk35 | 4 | unknown (added in dbversion 0x0c) |
240 | unk36 | 4 | unknown (added in dbversion 0x0c) |
244 | unk37 | 4 | unknown (added in dbversion 0x13) |
248 | gaplessData | 4 | The size in bytes from first Synch Frame (which is usually the XING frame that includes the LAME tag) until the 8th before the last frame. The gapless playback does not work for MP3 files if this is set to zero. Maybe the iPod prepares the next track when rest 8 frames in the actual track. For AAC tracks, this may be zero. (added in dbversion 0x13) |
252 | unk38 | 4 | unknown (added in dbversion 0x0c) |
256 | gaplessTrackFlag | 2 | if 1, this track has gapless playback data (added in dbversion 0x13) |
258 | gaplessAlbumFlag | 2 | if 1, this track does not use crossfading in iTunes (added in dbversion 0x13) |
260 | unk39 | 20 | Appears to be a hash, not checked by the iPod |
288 | unk40 | 4 | unknown (seen set to 0xbf) |
300 | unk41 | 4 | unknown |
304 | unk42 | 4 | unknown (always 0x00 ?) |
308 | unk43 | 4 | unknown (previously length 8, seen as 0x818080808080) |
312 | unk44 | 2 | unknown (previously length 8, seen as 0x818080808080) |
314 | AlbumID | 2 | album id from the album list (previously unknown length 8, seen as 0x818080808080) |
352 | mhii-link | 4 | Setting this offset to != 0 triggers the 'Right-Pane-Artwork-Slideshow' on late 2007 iPods (3g Nano) and causes the iPod to use this value to do artwork lookups (dbid_1 will be ignored!). This value should be set to the id of the corresponding ArtworkDB mhii (Offset 16) |
The rest of the mhit is zero padded. |
The MHIT is followed by several Data Objects which have string types. At minimum, it must have a Location type MHOD, in order to tell the iPod where the file is located on the iPod itself. It always has a FileType MHOD as well, although it's not totally necessary.
Playlist List
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhlp |
4 | header length | 4 | size of the mhlp header |
8 | number of playlists | 4 | the number of playlists on the iPod. This includes the Library playlist. |
rest of header is zero padded |
The Playlist List has all the playlists as its children. The very first playlist *must* be the Library playlist. This is a normal playlist, but it has the special "hidden" bit set in it, and it contains all the songs on the iPod (in no particular order).
Playlist
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhyp |
4 | header length | 4 | size of the mhyp header |
8 | total length | 4 | size of the header and all child records |
12 | Data Object Child Count | 4 | number of Data Objects in the List |
16 | Playlist Item Count | 4 | number of Playlist Items in the List |
20 | Is Master Playlist flag | 1 | 1 if the playlist is the Master (Library) playlist, 0 if it is not. Only the Master (Library) Playlist should have a 1 here. |
21 | unk | 3 | Probably three more flags, the first of which has been observed to have been set to 1 for some playlists. |
24 | timestamp | 4 | time of the playlists creation |
28 | persistent playlist ID | 8 | a unique, randomly generated ID for the playlist |
36 | unk3 | 4 | Always zero? |
40 | String MHOD Count | 2 | This appears to be the number of string MHODs (type < 50) associated with this playlist (typically 0x01). Doesn't seem to be signficant unless you include Type 52 MHODs. Formerly known as unk4. |
42 | Podcast Flag | 2 | This is set to 0 on normal playlists and to 1 for the Podcast playlist. If set to 1, the playlist will not be shown under 'Playlists' on the iPod, but as 'Podcasts' under the Music menu.. The actual title of the Playlist does not matter. If more than one playlist is set to 1, they don't show up at all. They also don't show up if you set this to 1 on one playlist and 2 on the other. Please note that podcast playlists are organized slightly different than ordinary playlists (see below). |
44 | List Sort Order | 4 | The field that the playlist will be sorted by. See list below. |
rest of header is zero padded |
The structure of the Playlists are different than most others. Each Playlist looks like this, conceptually:
<mhyp> <mhod type=1>Playlist Name</mhod> <mhod type=50>Smart Playlist Info</mhod> (optional) <mhod type=51>Smart Playlist Rules</mhod> (optional) ... <mhip>Playlist Item</mhip> <mhod type=100>Position Indicator</mhod> <mhip>Playlist Item</mhip> <mhod type=100>Position Indicator</mhod> ... </mhyp>
The point being that these are all considered in the MHYP for the size calculations. However, in the "Data Object" child count, ONLY those MHODs that come before the first MHIP are counted. The "position indicators" are children of the MHIPs (older firmwares had a bug in this respect).
List Sort Order
1 - playlist order (manual sort order) 2 - ??? 3 - songtitle 4 - album 5 - artist 6 - bitrate 7 - genre 8 - kind 9 - date modified 10 - track number 11 - size 12 - time 13 - year 14 - sample rate 15 - comment 16 - date added 17 - equalizer 18 - composer 19 - ??? 20 - play count 21 - last played 22 - disc number 23 - my rating 24 - release date (I guess, it's the value for the "Podcasts" list) 25 - BPM 26 - grouping 27 - category 28 - description 29 - show 30 - season 31 - episode number
Podcasts
The podcasts playlist is organized slightly differently, in the Type 3 MHSD. For example:
mhyp (MHODs: 2, MHIPs: 5, hidden: 0, list sort order: 0x18) mhod (type: 1, string: 'Podcasts') mhod (type: 100) mhip (MHODs: 1, groupflag: 256, groupid: 8232, trackid: 0, timestamp: 0, groupref: 0) mhod (type: 1, string: 'Example podcast') mhip (MHODs: 1, groupflag: 0, groupid: 8233, trackid: 8230, timestamp: 3206828281, groupref: 8232) mhod (type: 100) mhip (MHODs: 1, groupflag: 0, groupid: 8234, trackid: 8226, timestamp: 3206828379, groupref: 8232) mhod (type: 100) mhip (MHODs: 1, groupflag: 0, groupid: 8235, trackid: 8228, timestamp: 3206828327, groupref: 8232) mhod (type: 100) mhip (MHODs: 1, groupflag: 0, groupid: 8236, trackid: 8224, timestamp: 3206828394, groupref: 8232) mhod (type: 100)
The first mhip (probably identified by groupflag==256) contains the name of a podcast which will then appear as a submenu of the Podcasts menu on the iPod. The other mhips (which reference the episodes in that podcast) seem to use the groupref field to link to their 'parent' mhip (using the groupid field). At the same time the groupids of the episodes are unique as well, but don't seem to be used anywhere else.
Playlist Item
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhip |
4 | header length | 4 | size of the mhip header |
8 | total length | 4 | size of the header and all child records |
12 | Data Object Child Count | 4 | number of mhod following this Playlist Item (always 1 so far) |
16 | Podcast Grouping Flag | 2 | Formerly unk1. 0x0 = normal file. 0x100 = Podcast Group. Podcast Groups will be followed by a single child, an MHOD type 1 string, which specifies the name of the Podcast Group. They will also have a 0 (zero) for the Track ID. This field used to be some kind of correlation ID or something, but this may have been a bug. In any case, the old way breaks iPods now, and this should be set to zero on all normal songs. |
18 | unk4 | 1 | 0 or 1 in iTunes 7.2. |
19 | unk5 | 1 | 0 or 8 in iTunes 7.2. |
20 | Group ID (?) | 4 | Formerly unk2. A unique ID for the track. It appears it is made sure that this ID does not correspond to any real track ID. Doesn't seem to correlate to anything, but other bits reference it. See Podcast Grouping Reference below. |
24 | track ID | 4 | the ID number of the track in the track list. See Track Item for more info |
28 | timestamp | 4 | some kind of time stamp, possibly time the song was added to the playlist |
32 | Podcast Grouping Reference | 4 | Formerly unk3. This is the parent group that this podcast should be listed under. It should be zero the rest of the time. |
rest of header is zero padded |
For purposes of size calculations, Playlist Items have no children. However, every Playlist Item is invariably followed by a Data Object of type 100, which contains nothing but a number that is used to order/sort the playlist. See the Playlist description above for more information.
Please note that starting with iTunes 4.9 (mhbd file version number 0x0d) the Type 100 MHOD following the Playlist Item is considered a child of the Playlist Item and is included into the size calculation. The old behaviour was probably a bug in iTunes.
Data Object
The Data Object is a complex beast. It's used in many places in the iTunesDB file, and there are many forms of it. We'll cover the forms one by one.
value | description |
---|---|
1 | Title |
2 | Location (this string should be less than 112 bytes/56 UTF-16 chars (not including the terminating \0) or the iPod will skip the song when trying to play it) |
3 | Album |
4 | Artist |
5 | Genre |
6 | Filetype |
7 | EQ Setting |
8 | Comment |
9 | Category - This is the category ("Technology", "Music", etc.) where the podcast was located. Introduced in db version 0x0d. |
12 | Composer |
13 | Grouping |
14 | Description text (such as podcast show notes). Accessible by selecting the center button on the iPod, where this string is displayed along with the song title, date, and timestamp. Introduced in db version 0x0d. |
15 | Podcast Enclosure URL. Note: this is either a UTF-8 or ASCII encoded string (NOT UTF-16). Also, there is no mhod::length value for this type. Introduced in db version 0x0d. |
16 | Podcast RSS URL. Note: this is either a UTF-8 or ASCII encoded string (NOT UTF-16). Also, there is no mhod::length value for this type. Introduced in db version 0x0d. |
17 | Chapter data. This is a m4a-style entry that is used to display subsongs within a mhit. Introduced in db version 0x0d. |
18 | Subtitle (usually the same as Description). Introduced in db version 0x0d. |
19 | Show (for TV Shows only). Introduced in db version 0x0d? |
20 | Episode # (for TV Shows only). Introduced in db version 0x0d? |
21 | TV Network (for TV Shows only). Introduced in db version 0x0d? |
22 | Album Artist. Introduced in db version 0x13? |
23 | Artist name, for sorting. Artists with names like "The Beatles" will be in here as "Beatles, The". Introduced in db version 0x13? |
24 | Appears to be a list of keywords pertaining to a track. Introduced in db version 0x13? |
25 | Locale for TV show? (e.g. "us-tv||0|", v.0x18) |
27 | Title, for sorting. |
28 | Album, for sorting. |
29 | Album-Artist, for sorting. |
30 | Composer, for sorting. |
31 | TV-Show, for sorting. |
32 | Unknown, created by iTunes 7.1 for video tracks. Binary field, no string. | 50 | Smart Playlist Data |
51 | Smart Playlist Rules |
52 | Library Playlist Index |
53 | Unknown, created by iTunes 7.2, similar to MHOD52 |
100 | Seems to vary. iTunes uses it for column sizing info as well as an order indicator in playlists. |
200 | Album (in Album List, iTunes 7.1) |
201 | Artist (in Album List, iTunes 7.1) |
202 | Artist, for sorting (in Album List, iTunes 7.1) |
203 | Podcast Url (in Album List, iTunes 7.1) |
204 | TV Show (in Album List, v. 0x18) |
String Types
The simplest form of MHOD. These are any MHOD with a "type" that is less than 15.
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhod |
4 | header length | 4 | size of the mhod header. This is always 0x18 for string type MHOD's. |
8 | total length | 4 | size of the header and the string it contains |
12 | type | 4 | the type indicator |
16 | unk1 | 4 | unknown |
20 | unk2 | 4 | unknown |
24 | position | 4 | In type 100 mhod's in playlists, this is where the playlist order info is. It does not seem to be significant in string mhod's (except for location - see following notes).
Note: This field does not exist in ArtworkDB string dohms. This was observed to be 2 for inversed endian ordered iTunesDBs for mobile phones with UTF8 strings and 1 for standard iPod iTunesDBs with UTF16 strings. Note: If you leave this set to zero on the type 2 (location) string MHOD of a Song (mhit) record, the track will show on the menu, but will not play. |
28 | length | 4 | Length of the string, in bytes. If the string is UTF-16, each char takes two bytes. The string in the iTunesDB is not NULL-terminated either. Keep this in mind. Be careful with very long strings - it has been observed that strings longer than ~512 characters will cause the iPod to continously reboot when it attempts to read the database. |
32 | unknown | 4 | unknown. It was thought that this was string encoding: 0 == UTF-16, 1 == UTF-8, however, recent iTunesDB files have had this set to 1 even with UTF-16 strings. Therefore this is definitely incorrect, and the correct meaning has not yet been discovered yet. |
36 | unk4 | 4 | unknown |
40 | string | length | The string. |
string mhods are NOT zero padded |
Podcast URLs (types 15-16)
Introduced in db version 0x0d, MHOD's with type 15 and 16 hold the Enclosure and RSS URL for the Podcast. The string is probably UTF-8, but only Unicode symbols U+0000 through U+007F (a.k.a ASCII) have been observed.
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhod |
4 | header length | 4 | size of the mhod header. This is always 0x18 for string type MHOD's. |
8 | total length | 4 | size of the header and the string it contains |
12 | type | 4 | the type indicator ( 15 or 16 ) |
16 | unk1 | 4 | unknown (always 0?) |
20 | unk2 | 4 | unknown (always 0?) |
24 | string | (total length - header length) | The string. |
string mhods are NOT zero padded |
Chapter Data (type 17)
The chapter data is a style of data that's very, very out of place in this file, but is here nonetheless. It defines where the chapter stops are in the track, as well as what info should be displayed for each section of the track. It seems that the format of this mhod changed significantly over time. The following is analysed from an iTunesDB version 0x13 (iTunes 7.0).
Chapter Data mhod details
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhod |
4 | header length | 4 | size of the mhod header. This is always 0x18. |
8 | total length | 4 | size of the mhod |
12 | type | 4 | the type indicator ( 0x11 = 17 ) |
16 | unk1 | 4 | unknown (always 0?) |
20 | unk2 | 4 | unknown (always 0?) |
24 | unk3 | 4 | unknown (always 0?) This is not part of the header (otherwise the header length would have been different), but it is also not part of the first atom. |
28 | unk4 | 4 | unknown (always 0?) This is not part of the header (otherwise the header length would have been different), but it is also not part of the first atom. |
32 | unk5 | 4 | unknown (always 0?) This is not part of the header (otherwise the header length would have been different), but it is also not part of the first atom. |
36 | data | (total length - header length - 12) | The chapter stop data atoms, starting with a "sean" atom (see below).
This part of the mhod is not little-endian like the rest of the file. It's big-endian/ E.g. the value 0x0123 in a 4 byte word is found as 00 00 01 23. It is also arranged in a tree like structure, much like the iTunesDB itself is, only the information is in a slightly different arrangement. |
Chapter Data Atom Layout
The atoms appear to be arranged in the following layout:
sean (exactly one atom of this type is present, childcount is number of chapters + 1 for the hedr atom) chap (chapter indicator, childcount is always 1) name (contains a UTF16 string with name of the chapter or Artist name, childcount is always 0) chap (next chapter) name (and so on)... ... hedr (signals the end, childcount is always 0)
There are multiple "chap" entries, one for each chapter.
Older DBs seem to have a different, more complex layout, like this:
sean (?) chap (chapter indicator ?) name (contains a UTF16 string with name of the chapter or Artist name) ploc (position/location?) trak (specifies track number, perhaps? This should be obvious after looking at some examples) urlt (contains a UTF16 string with the name of the song in the chapter or some kind of subname) url (contains a UTF8 string with a URL) chap (next chapter) name (and so on)... ... hedr (signals the end)
Chapter Data Atoms
Each atom consists of the following:
offset | field | size | value |
---|---|---|---|
0 | size | 4 | size of the atom and all its childrenCaution: This is different to all other structures in the file, where the name always comes first. Here, the length is the first word of the atom! |
4 | atom name | 4 | the name of the atom |
8 | startpos/unk1 | 4 | For chap atoms: the starting position of this chapter in ms, except for the very first chap where this field is 1 (not 0 as expected). For all other atoms: always 1? |
12 | number of childs | 4 | the number of childs |
16 | unk2 | 4 | always 0? |
20 | data | varies | some kind of data or children |
Chapter Data String Atoms (UTF16)
UTF16 String entries in these atoms (like 'name') fit the following mold:
offset | field | size | value |
---|---|---|---|
0 | size | 4 | size of the atom and all its children (0x16 + 2*string length in characters, e.g. for a 8 char string this is 0x26) |
4 | atom name | 4 | the name of the atom |
8 | unknown | 4 | always 1? |
12 | unk1 | 4 | always 0? (child count) |
16 | unk2 | 4 | always 0? |
20 | string length | 2 | string length in characters |
22 | string | length *2 | UTF16 string, 2 bytes per character |
Chapter Data String Atoms (UTF8)
UTF8 entries fit the following mold:
offset | field | size | value |
---|---|---|---|
0 | size | 4 | size of the atom and all its children |
4 | atom name | 4 | the name of the atom |
8 | unknown | 4 | always 1? |
12 | unknown | 4 | varies.. some kind of type? |
16 | null | 8 | zeros |
24 | string | size - 24 | UTF8 string, 1 byte per character |
Chapter Data hedr Atom
offset | field | size | value |
---|---|---|---|
0 | size | 4 | size of the atom, 0x1c |
4 | atom name | 4 | the name of the atom, 'hedr' |
8 | unk1 | 4 | always 1? |
12 | number of childs | 4 | the number of childs, always 0 |
16 | unk2 | 4 | always 0 |
20 | unk3 | 4 | always 0 |
24 | unk4 | 4 | always 1 |
Smart Playlist Data (type 50)
A slightly more complex MHOD. These are any MHOD with a "type" that is 50.
This MHOD defines the stuff in the Smart playlist that is not the "rules". Basically all the checkboxes and such. It's pretty straightforward.
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhod |
4 | header length | 4 | size of the mhod header. |
8 | total length | 4 | total length of the mhod |
12 | type | 4 | the type indicator ( 50 ) |
16 | unk1 | 4 | unknown |
20 | unk2 | 4 | unknown |
24 | live update | 1 | Live Update flag. 0x01 = on, 0x00 = off |
25 | check rules | 1 | Rules enable flag. 0x01 = on, 0x00 = off. When this is enabled, Rules from the type 51 MHOD will be used. |
26 | check limits | 1 | Limits enable flag. 0x01 = on, 0x00 = off. When this is enabled, Limits listed below will actually be used. |
27 | limit type | 1 | Limit Type. See below for the list of limit types. |
28 | limit sort | 1 | Limit Sort. See below for the list of limit sorting types. |
29 | unknown | 3 | always zero bytes |
32 | limit value | 4 | The actual value used for the limit |
36 | match checked only | 1 | match checked only flag, 0x01 = on, 0x00 = off. When this is enabled, only songs marked as "checked" will be matched. Checked is a field in the mhit. |
37 | reverse limit sort | 1 | Reverse the Limit Sort flag. 0x01 = on, 0x00 = off. When this is enabled, the sort will be reversed. More on this below. |
the mhod IS zero padded at the end (58 null bytes) |
value | description |
---|---|
1 | Minutes |
2 | Megabytes |
3 | Songs |
4 | Hours |
5 | Gigabytes |
value | description |
---|---|
0x02 | Random |
0x03 | Song Name (alphabetical) |
0x04 | Album (alphabetical) |
0x05 | Artist (alphabetical) |
0x07 | Genre (alphabetical) |
0x10 | Most Recently Added |
0x14 | Most Often Played |
0x15 | Most Recently Played |
0x17 | Highest Rating |
When the Reverse Limit Sort flag is set, the sort will be reversed. So most recently added becomes least recently added, and highest rating becomes lowest rating, and so on. It's just reversing the sorted list before applying the limit to it.
Smart Playlist Rules (type 51)
The most complex (and annoying) MHOD. These are any MHOD with a "type" that is 51.
This MHOD defines all the rules in the Smart Playlist. It is not straightforward at all. In fact, I have to break it down into subtypes itself.
If you've used iTunes, you know what a rule looks like. "Rating is less than 3 stars", for example. The rule consists of three parts.
The first part is the "field". In our example, the field is "Rating". It's the very first thing in the rule and the first pull down box in iTunes. Simple enough.
The second part is the "action". In our example, the action is "is less than". In iTunes, it's the second pull down box. Also pretty simple.
The final part is the "value". In our example, it'd be "3 stars". Since stars are always multiplied by 20 for whatever reason, it'd be "60" for our example, in the iTunesDB file.
We'll cover these one at a time.
Important Note about endian-ness
Smart Playlist Rules MHODs are NOT wholly little-endian. Everything after the "SLst" to the end of the MHOD is big-endian. This is important to remember, especially when dealing with the Action types.
Smart Playlist Rule Fields
Fields are easy. Much more so than Actions. The "expected comparison" column will make more sense when you see the Values explained below.
value | description | expected comparison |
---|---|---|
0x02 | Song Name | String |
0x03 | Album | String |
0x04 | Artist | String |
0x05 | Bitrate | Integer |
0x06 | Sample Rate | Integer |
0x07 | Year | Integer |
0x08 | Genre | String |
0x09 | Kind | String |
0x0a | Date Modified | Timestamp |
0x0b | Track Number | Integer |
0x0c | Size | Integer |
0x0d | Time | Integer |
0x0e | Comment | String |
0x10 | Date Added | Timestamp |
0x12 | Composer | String |
0x16 | Play Count | Integer |
0x17 | Last Played | Timestamp |
0x18 | Disc Number | Integer |
0x19 | Stars/Rating | Integer (multiply by 20 for stars/rating) |
0x1f | Compilation | Integer |
0x23 | BPM | Integer |
0x27 | Grouping | String (see special note) |
0x28 | Playlist | Integer - the playlist ID number (see special note) |
0x36 | Description | String |
0x37 | Category | String |
0x39 | Podcast | Integer |
0x3c | Video Kind | Logic integer, works on mediatype |
0x3e | TV Show | String |
0x3f | Season Nr | Integer |
0x44 | Skip Count | Integer |
0x45 | Last Skipped | Timestamp |
0x47 | Album Artist | String |
Special Note about Grouping and Playlist fields - They don't work with Live Updating on 3rd gen iPods, yet. This might get fixed in a future firmware release. Maybe.
Smart Playlist Rule Actions
The Action type is a 4 byte field. It is a bitmapped value, meaning that each bit of these four bytes has a different meaning.
bit | description |
---|---|
0 | The action is referring to a string value if set, not a string if not set |
1 | NOT flag. If set, this negates the rule. Is becomes is not, contains becomes does not contain, and so forth. |
bit | description |
---|---|
0 | Simple "IS" query |
1 | Contains |
2 | Begins with |
3 | Ends with |
4 | Greater Than |
5 | Greater Than or Equal To |
6 | Less Than |
7 | Less Than or Equal To |
8 | Is in the Range |
9 | In the Last |
10 | Is / Is Not (binary AND, only used for "Video Kind" so far) |
This is complicated, obviously, and iTunes abstracts this all by defining various actions for various fields. Here's the complete possible list of actions, including those that iTunes does not have but which still work on the iPod:
value | action |
---|---|
0x00000001 | Is Int (also Is Set in iTunes) |
0x00000010 | Is Greater Than (also Is After in iTunes) |
0x00000020 | Is Greater Than Or Equal To (not in iTunes) |
0x00000040 | Is Less Than (also Is Before in iTunes) |
0x00000080 | Is Less Than Or Equal To (not in iTunes) |
0x00000100 | Is in the Range |
0x00000200 | Is in the Last |
0x00000400 | Is / Is Not (Binary AND, used for media type so far) |
0x01000001 | Is String |
0x01000002 | Contains |
0x01000004 | Starts With |
0x01000008 | Ends With |
0x02000001 | Is Not Int (also Is Not Set in iTunes) |
0x02000010 | Is Not Greater Than (not in iTunes) |
0x02000020 | Is Not Greater Than Or Equal To (not in iTunes) |
0x02000040 | Is Not Less Than (not in iTunes) |
0x02000080 | Is Not Less Than Or Equal To (not in iTunes) |
0x02000100 | Is Not In the Range (not in iTunes) |
0x02000200 | Is Not In The Last |
0x03000001 | Is Not |
0x03000002 | Does Not Contain |
0x03000004 | Does Not Start With (not in iTunes) |
0x03000008 | Does Not End With (not in iTunes) |
Smart Playlist Rule Values
Values are generally pretty straightforward. For String rules, it's a string. For Integer and Timestamp rules, it's a bit more complicated. Furthermore, the "In the Last" type action requires a Units value as well.
So there are two major rule formats, the String Rule and the Non-String Rule.
offset | field | size | value |
---|---|---|---|
0 | field | 4 | The Field type |
4 | action | 4 | The Action type |
8 | padding | 44 | zero padding |
52 | length | 4 | length of the string, in bytes. Maximum length is 255 |
56 | string | length | the string in UTF-16 format (2 bytes per character) |
rules are NOT zero padded at the end |
offset | field | size | value |
---|---|---|---|
0 | field | 4 | The Field type |
4 | action | 4 | The Action type |
8 | padding | 44 | zero padding |
52 | length | 4 | always 0x44 for non-string types |
56 | from value | 8 | the from value in an 8 byte form (unsigned int64) |
64 | from date | 8 | the from date in an 8 byte form (signed int64) |
72 | from units | 8 | the from units in an 8 byte form (unsigned int64) |
80 | to value | 8 | the to value in an 8 byte form (unsigned int64) |
88 | to date | 8 | the to date in an 8 byte form (signed int64) |
96 | to units | 8 | the to units in an 8 byte form (unsigned int64) |
104 | unknown | 20 | unknown, used by all field types, unknown purpose |
rules are NOT zero padded at the end |
For integer type rules, the from and to values are the ones that you care about, the date = 0, and the units = 1.
Example: BPM is less than 150 field = 0x23 (BPM) action = 0x00000040 (is less than) from and to value = 150 from and to date = 0 from and to units = 1
Example: BPM is in the range 70 to 150 field = 0x23 (BPM) action = 0x00000100 (is in the range) from value = 70 to value = 150 from and to date = 0 from and to units = 1
For binary and type rules, the from and to values are the ones that you care about, the date = 0, and the units = 1.
Example: Video Kind is TV-Show field = 0x3c (Video Kind) action = 0x00000400 (Is / Is Not) from and to value = 0x0040 from and to date = 0 from and to units = 1
Example: Video Kind is not TV-Show field = 0x3c (Video Kind / mediatype) action = 0x00000400 (Is / Is Not) from and to value = 0x0e22 from and to date = 0 from and to units = 1
For the latter one would expect a value of 0x0022 (either Movie or Music Video). The additional 0x0e00 in the mask hints for further video types to come.
Timestamp type rules use the same format as integer type rules, only the from and to values are Mac timestamps. This is the number of seconds since 1/1/1904.
Example: Date Added is in the range 6/19/2004 to 6/20/2004 field = 0x10 (Date Added) action = 0x00000100 (is in the range) from value = bcfa83ff (6/19/2004) to value = 0xbcfbd57f (6/20/2004) from and to date = 0 from and to units = 1
For "in the last" type rules, the from and to values are set to a constant of 0x2dae2dae2dae2dae. The from dates become the value, and the from units becomes the unit you're measuring in. The way to think of this is that it's saying "Today (2dae) plus this number of units".
Example: Last Played Time is in the last 2 weeks. field = 0x17 (Last Played Time) action = 0x00000200 (is in the last) from value = 0x2dae2dae2dae2dae from date = -2 from units = 604800 (number of seconds in a week) to value = 0x2dae2dae2dae2dae to date = 0 to units = 1
That rule is saying "Today minus 2 times this number of seconds" which is 2 weeks before "now", whatever now happens to be.
If you're creating your own rules in an iTunesDB, you may find it more convienent to leave the units set to "1" all the time and just put the number of seconds into the date field. This is perfectly acceptable and the iPod can handle it just fine. If you're not sure how to make a particular rule, create it or a similar one in iTunes and put it on the iPod, then examine the iTunesDB file to see how it did it.
But if you're programming the iPod side of things, you need to be able to correctly understand the units field and deal with it accordingly. The best way to do this is to always compare the contents of the field in question with (value+date*unit), and replacing the "value" with the current timestamp ("now") when it is equal to 3,291,618,603,768,360,366 (0x2dae2dae2dae2dae). This will work for *all* integer and timestamp comparisons if done correctly. It's also exactly what the Apple iPod firmware does. It's also why you have to set the time/date on an iPod for these smart playlists to work correctly (3rd gen and up).
Also, remember that all timestamps should be dealt with in Apple format, which is the number of seconds since 1/1/1904.
Putting It All Together
So, now you know how to create a given rule. All that's left is to put all the rules together and shove them into a type 51 MHOD.
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhod |
4 | header length | 4 | size of the mhod header. |
8 | total length | 4 | size of the header and the rules it contains |
12 | type | 4 | the type indicator ( 51 ) |
16 | unk1 | 4 | unknown |
20 | unk2 | 4 | unknown |
24 | smart list rules identifier | 4 | "SLst" (note that this is the point at which bytes are no longer little-endian in the mhod.. it switches to big-endian at this point) |
28 | unk5 | 4 | unknown |
32 | number of rules | 4 | number of rules |
36 | rules operator | 4 | 0 = AND (as in "Match All"), 1 = OR (as in "Match Any") |
40 | padding | 120 | zero padding |
160 | rules | whatever size the rules are | the rules themselves, one after another. |
the mhod is NOT is zero padded at the end |
Library Playlist Index (type 52)
The type 52 MHOD is only found as a child of the Main Library Playlist. It is an index of the mhit's ordered by the major categories in the Browse menu. The purpose of these mhod's is to speed up the operation of the Browse menu itself. This is how it displays the information so quickly when selecting one of the major categories, it's all presorted for the iPod in these MHOD's.
Note that this MHOD is not mandatory, however the iPod menu system will operate much slower without it (on large libraries), as it will have to build the information provided here on the fly. Therefore it is recommended to build this MHOD for anything more than trivial numbers of songs.
Essentially, every MHIT is numbered from 0 to the total number of songs-1. The type 52 MHOD contains a list of these index numbers using one of the strings contained in these MHIT's, ordered alphabetically.
To build one of these, take all your songs, order them alphabetically by one of these fields, then simply insert the index numbers of the ordered songs into the type 52 mhod.
type number | field that it indexes |
---|---|
0x03 | Title |
0x04 | Album, then Disc/Tracknumber, then Title |
0x05 | Artist, then Album, then Disc/Tracknumber, then Title |
0x07 | Genre, then Artist, then Album, then Disc/Tracknumber, then Title |
0x12 | Composer, then Title |
0x1d | Observed with iTunes 7.2, probably sorted by 'Show' first. Someone with TV shows on his iPod please fill in the secondary sort orders. |
0x1e | Observed with iTunes 7.2, probably sorted by 'Season Number' first. Someone with TV shows on his iPod please fill in the secondary sort orders. |
0x1f | Observed with iTunes 7.2, probably sorted by 'Episode Number' first. Someone with TV shows on his iPod please fill in the secondary sort orders. |
0x23 | Observed with iTunes 7.3 (but may possibly exist in earlier versions, too), unknown what this does. |
0x24 | Observed with iTunes 7.3 (but may possibly exist in earlier versions, too), unknown what this does. |
(Note that the above list roughly matches the limit sort list.. I think that these lists are actually the same in some way.)
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhod |
4 | header length | 4 | size of the mhod header. |
8 | total length | 4 | size of the header and all the index entries |
12 | type | 4 | the type indicator ( 52 ) |
16 | unk1 | 4 | unknown (always zero) |
20 | unk2 | 4 | unknown (always zero) |
24 | index type | 4 | what this index is sorted on (see list above) |
28 | count | 4 | number of entries. Always the same as the number of entries in the playlist, which is the same as the number of songs on the iPod. |
32 | null padding | 40 | lots of padding |
72 | index entries | 4 * count | The index entries themselves. This is an index into the mhit list, in order, starting from 0 for the first mhit. |
the mhod is NOT zero padded at the end |
Type 53
The type 53 MHOD is only found as a child of the Main Library Playlist.
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhod |
4 | header length | 4 | size of the mhod header. |
8 | total length | 4 | size of the header and all the index entries |
12 | type | 4 | the type indicator ( 53 ) |
16 | unk1 | 4 | unknown (always zero) |
20 | unk2 | 4 | unknown (always zero) |
24 | index type | 4 | what this index is sorted on (see list above) |
28 | count | 4 | number of entries. Unused letters are left out and umlauts (at least German ones) are added after the letter they are derived from. Don't yet know about the order of the French accented letters. |
32 | null padding | 8 | lots of padding |
40 | index entries | 12 * count | The index entries themselves. |
the mhod is NOT zero padded at the end |
offset | field | size | value |
---|---|---|---|
0 | letter | 4 | The letter of this table entry. Looks like uppercase UTF-16LE with 2 padding null bytes (i.e. A would be 0x00000041 little endian / 0x41000000 big endian) |
4 | header length | 4 | the number of the first entry in the corresponding MHOD52 index starting with this letter. Zero-based and incremented by one for each entry, not 4. |
8 | total length | 4 | the count of entries starting with this letter in the corresponding MHOD52. |
I don't know how these are associated with the corresponding MHOD52s, I would guess by the sort order field, but I'm not sure because they always turn up immediately after their MHOD52. Could someone please have a look at this and the other yet unknown things above?
Type 100
There are a couple forms of Type 100 MHOD's (that we know of).
The first form is at the beginning of every playlist (before any MHIP entries). Only iTunes puts it there, and only iTunes uses it. It contains information on what columns to display, and what size to display them as, when displaying the playlist in iTunes when the iPod is in a manual mode. This is absolutely optional. The iPod itself doesn't appear to use it in any way.
The second form is after every MHIP in a playlist, there's a small type 100 MHOD. It gives an order number to the song immediately before it. It is not optional, but it's also not particularly useful.
Playlist Column Definitions Header
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhod |
4 | header length | 4 | size of the mhod header. This is always 0x18 for this type of MHOD. |
8 | total length | 4 | size of the header and it's data. This is always 0x288 for this type of MHOD. |
12 | type | 4 | the type indicator ( 100 ) |
16 | unk1 | 4 | unknown, always 0 |
20 | unk2 | 4 | unknown, always 0 |
24 | unk3 | 4 | unknown, always 0 |
28 | unk4 | 8 | unknown, appears to be 0x0088004A02EF0281 for everything except normal playlists. Some kind of identifier? |
36 | unk8 | 4 | unknown, always 0 |
40 | unk9 | 2 | unknown, appears to be 130 for normal playlists and 200 for everything else |
42 | unk10 | 2 | unknown, appears to be 3 for the iPod library and 1 for everything else |
44 | sort type | 4 | the sort type for this playlist. Use this value to figure out which column is selected by mapping it to the correct column ID (listed below). |
48 | number of columns | 4 | the number of columns visible in iTunes for this playlist. In iTunes 6, this value can be anywhere from 2 to 28. |
52 | unknown1 | 2 | unknown (always 1?) (Selected column?) |
54 | unknown2 | 2 | unknown (always 0?) (Column sort direction? asc/desc) |
56 | column definitions | 16 * number of columns | the column definitions |
after the column definitions, the rest of the MHOD is zero-padded |
Column Definition
Each column definition only consists of an ID for the playlist and the sort direction for the column. The order they appear in this MHOD are the order they appear in iTunes, from left to right. The first two columns are always song position and title, in that order.
offset | field | size | value |
---|---|---|---|
0 | ID | 2 | the ID for this column, see below for possible values |
2 | width | 2 | the width of the column, in pixels |
4 | sort direction | 4 | if equal to 0x1, the sort is reversed for this column. Set to 0x0 otherwise. |
8 | unknown | 4 | seems to be null padding |
12 | unknown | 4 | seems to be null padding |
ID | description |
---|---|
0x01 | position; leftmost column in all playlists |
0x02 | Name |
0x03 | Album |
0x04 | Artist |
0x05 | Bit Rate |
0x06 | Sample Rate |
0x07 | Year |
0x08 | Genre |
0x09 | Kind |
0x0A | Date Modified |
0x0B | Track Number |
0x0C | Size |
0x0D | Time |
0x0E | Comment |
0x10 | Date Added |
0x11 | Equalizer |
0x12 | Composer |
0x14 | Play Count |
0x15 | Last Played |
0x16 | Disc Number |
0x17 | My Rating |
0x19 | Date Released (Podcasts group only) |
0x1A | BPM |
0x1C | Grouping |
0x1E | Category |
0x1F | Description |
0x21 | Show |
0x22 | Season |
0x23 | Episode Number |
Playlist Order Entry
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhod |
4 | header length | 4 | size of the mhod header. This is always 0x18 for this type of MHOD. |
8 | total length | 4 | size of the header and it's data. This is always 0x2C for this type of MHOD. |
12 | type | 4 | the type indicator ( 100 ) |
16 | unk1 | 4 | unknown, always 0 |
20 | unk2 | 4 | unknown, always 0 |
24 | position | 4 | Position of the song in the playlist. These numbers do not have to be sequentially ordered, numbers can be skipped. |
28 | unknown | 16 | zero padding |
Album List
Album List, first seen with iTunes 7.1. It was seen on iPod nano 2nd gen and Shuffle 2nd gen restored with iTunes 7.1.1, but not on iPod Video 30GB(restored with the same version of iTunes).
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhla |
4 | header length | 4 | size of the mhla header |
8 | number of album items | 4 | the total number of songs in the Album List |
rest of header is zero padded |
The Album List has Album Items as its children. The number of Album Items is the same all albums on iPod.
Album Item
offset | field | size | value |
---|---|---|---|
0 | header identifier | 4 | mhia |
4 | header length | 4 | size of the mhia header. Length is 0x58 |
8 | total length | 4 | size of the header and all child records |
12 | number of strings | 4 | number of strings (mhods) that are children of this mhia |
16 | unknown | 2 | (previously long length 4 with possibly album ID) |
18 | album id for track | 2 | album ID (v. 0x18 file) (previously long length 4) |
20 | unknown | 8 | timestamp? (v. 0x18 file) |
28 | unknown | 4 | always 2? (v. 0x18 file) |
Usually mhia has two child strings: album title and artist name.