The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package MacOSX::iTunes::FileFormat;

=head1 NAME

iTunes Music Library File Format

=head1 SYNOPSIS

This file describes the C<iTunes Music Library> file format for 
application versions 1.1.2 and 3.0.

=head1 DESCRIPTION

The C<iTunes Music Library> file contains a series of variable length
blocks.  The first part of the file refers to iTunes in general and
to the number of playlists the file contains. The middle part holds
all of the MP3 data, which is only stored once per item.  Each item
has a unique identifier used later in the file.  The last part of the
file contains a list of playlists, and within each playlist is a list
of the item identifiers from the middle of the file.

=head2 Markers

Each block of data begins with a four letter marker which denotes
the type of block.  Some blocks contain sub-blocks, which means
you cannot simply read to the next marker.

The blocks show up roughly in this order:

=over 4

=item hdfm -- file header

=item hdsm -- part header ?

=item htlm -- master items list header ?

=item htim -- master item record

=item hohm -- data sublock, multi-purpose (in htim, hpim blocks)

=item hplm -- playlist list header ?

=item hpim -- start of playlist block

=item hptm -- item indentifier sub-block for hpim

=back

=head2 Block format

=over 4

=item hdfm

    Byte   Length  Comment
    -----------------------
      0       4     'hdfm'
      4       4     L = header length
      8       4     file length ?
     12       4     ?
     13       1     N = length of version string
     14       N     application version string
     14+N   L-N-17  ?

=item hdsm

    Byte   Length  Comment
    -----------------------
      0       4     'hdsm'
      4       4     L = header length
      8       4     ?
     12       4     block type ?
     16      L-16   ?

=item htlm

    Byte   Length  Comment
    -----------------------
      0       4     'htlm'
      4       4     L = header length
      8       4     number of songs
     12      L-12   ?

=item htim

    Byte   Length  Comment
    -----------------------
      0       4     'htim'
      4       4     L = header length (usually 156, or 0x9C)
      8       4     R = total record length, including sub-blocks
     12       4     N = number of hohm sub-blocks
     16       4     song identifier
     20       4     block type => (1, ?)
     24       4     ?
     28       4     Mac OS file type (e.g. MPG3)
     32       4     modification date
     36       4     file size, in bytes
     40       4     playtime, millisecs
     44       4     track number
     48       4     total number of tracks
     52       2     ?
     54       2     year
     56       2     ?
     58       2     bit rate
     60       2     sample rate
     62       2     ?
     64       4     volume adjustment (signed)
     68       4     start time, milliseconds
     72       4     end time, milliseconds
     76       4     playcount
     80       2     ?
     82       2     compilation (1 = yes, 0 = no)
     84      12     ?
     96       4     playcount again?
    100       4     last play date
    104       2     disk number
    106       2     total disks
    108       1     rating ( 0 to 100 )
    109      11     ?
    120       4     add date
    124      32     ?
    156      R-L    hohm sub blocks

=item hohm

The hohm block has a header, annotated immediately below, and a 
data-specific block.

    Byte   Length  Comment
    -----------------------
      0       4     'hohm'
      4       4     L = header length, usually 0x18
      8       4     R = total record length
     12       4     block type, (1, 2, 3, 4, 5, 6, 0x0b, 0x64)
     16      12     ?
     28     R-28    block specific data


=over 4

=item hohm block types

The data-specific structure follows the header structure of the 
hohm block.  Offsets start at 0', which is byte 28 in the record.
Sometimes these data appear to have null bytes alternate with
information bytes, as in the Perl string "\000H\000e\000l\000l\000o".
In that case, the null bytes count in the length of the data.

    Type  Decimal   Description
    --------------------------------------
     1              big bag of gook     
     2              song title
     3              album title
     4              artist name
     5              genre string (not number)
     6              file type (e.g. MPEG)
     8              comments
     b      11      URL
     c      12      composer
    3a      58      equalizer data?
    3c      60      equalizer preset (text)
    64     100      playlist name (used in hpim)

=item hohm type 1

    Byte   Length  Comment
    -----------------------
      0'      2     ?
      2       2     n = length of next thingy ?
      4       n     ?
      4+n     1     N = volume name length up to 27 (e.g. hard drive name)
      5+n     N     volume name
             27-N   left over bytes from volume name (null bytes)
              2     ?? (iTunes 3)
      5+n+N   1     M = filename length
      6+n+N   M     filename

      (let A = n+N+M )

       6+A    4     Mac OS file type
      10+A    4     Mac OS creator
      14+A   20     ?
      24+A    4     B = directory name length
      28+A    B     directory name
      28+A+B  C?    ? gook up to the sequence 0x5a_00_02_00 ? (iTunes 1)
                    ? gook up to the sequence 0x7f_00_02_00 ? (iTunes 3)

      (let A' = A+B+C )

      28+A'   2     D = length of fully qualified path
      30+A'   D    path

 =item hohm type 11 (0x0b)

    Byte   Length  Comment
    -----------------------
      0'     12      ?
     12       4      N = length of data
     16       8      ?
     24       N      URL

=item hohm type 100 (0x64)

    Byte   Length  Comment
    -----------------------
      0'     12      ?
     12       4      N = length of playlist name
     16       8      ?
     24       N      playlist name

=item other hohm types 

    Byte   Length  Comment
    -----------------------
      0'     12      ?
     12       4      N = length of data
     16       8      ?
     24       N      data



=back

=item hpim

    Byte   Length  Comment
    -----------------------
      0       4      hpim
      4       4      N = length of data
      8       4      ?
     12       4      ?
     16       4      number of items (hptm) in playlist


=item hptm

    Byte   Length  Comment
    -----------------------
      0       4      hpim
      4       4      N = length of data
      8      16      ?
     24       4      song key (from htim)
     28     N - 28   ?

=back

=cut

"See why 1984 won't be like 1984";

=head1 TO DO

* verify that this works on all available versions

=head1 BUGS

* i've guessed on almost everything in this document, but it seems
to work.

=head1 AUTHOR

Copyright 2002, brian d foy <bdfoy@cpan.org>

You may redistribute this under the same terms as Perl.

=cut