man Mac::iPod::GNUpod () - Add and remove songs from your iPod; read and write databases in iTunes and GNUpod format

NAME

Mac::iPod::GNUpod - Add and remove songs from your iPod; read and write databases in iTunes and GNUpod format

ABSTRACT

This is the module to do anything with your iPod, with methods for initializing your iPod, adding and removing songs, and reading and writing databases in the iTunes and GNUpod formats. This module was originally based on the GNUpod script package, written and distributed by Adrian Ulrich, (pab at blinkenlights.ch), <http://www.gnu.org/software/gnupod/>. However, a lot of development has occurred since then, making the module more flexible and more appropriate for CPAN. This module and the GNUpod scripts remain completely interoperablethey write the same file format and work in much the same way.

SYNOPSIS

    use Mac::iPod::GNUpod;

    my $ipod = Mac::iPod::GNUpod->new(mountpoint => '/mnt/ipod');

    # Read existing databases
    $ipod->read_gnupod;
    $ipod->read_itunes;

    # Add songs
    my $id = $ipod->add_song('~/music/The Foo Brothers - All Barred Up.mp3');

    # Get paths to songs
    my $path = $ipod->get_path($id);

    # Find the id numbers of existing songs
    my @yuck = $ipod->search(artist => 'Yoko Ono');

    # Remove songs based on id
    $ipod->rm_song(@yuck);

    # Write databases
    $ipod->write_gnupod;
    $ipod->write_itunes;

DESCRIPTION

Mac::iPod::GNUpod is a module designed to let you read the database(s) on your iPod and add and remove songs from it using Perl. It is based on the GNUpod script package written by Adrian Ulrich, which is available at <http://www.gnu.org/software/gnupod/>. You do NOT need to install the GNUpod scripts in order to use Mac::iPod::GNUpod module. The GNUpod scripts use a plaintext XML database alongside the binary iTunes database used internally by the iPod. This package is capable of reading and writing both the GNUpod database format and the iTunes database format, and can peacefully coexist with both.

Currently this module ONLY works with Unix and Unix-like systems. This probably includes Linux, FreeBSD, MacOS 10.x, and Solaris. OS-independence will come, someday.

Note that the GNUpod database format, the original GNUpod package, and much of the code in this module is (c) Adrian Ulrich.

This module is object oriented. A brief description of the methods needed to perform various tasks follows:

Preparing a blank or corrupted iPod

Your iPod must be formatted and mounted for this module to see it. It can be formatted in FAT32 (Windows) or HFS+ (Mac) format, just so long as your kernel supports it.

If your iPod is fresh out of the box, probably nothing needs to be done, but if its file structure has been corrupted you should initialize it with the init method.

If your databases have been lost or corrupted, you may use the restore method to find all of the songs on the iPod and rewrite fresh databases.

Reading and writing databases

You can read and write the iTunes DBs with the read_itunes and write_itunes methods respectively. Conversely, the GNUpod DBs are accessed with read_gnupod and write_gnupod.

The advantage of the GNUpod DB is that it can be read and written many times faster than the iTunes DB can, so your scripts will run much faster than if you use only the iTunes format. The following scripts are functionally identical:

A:

    my $ipod = Mac::iPod::GNUpod->new(mountpoint => '/mnt/ipod');

    $ipod->read_itunes;

    # Etc ...

    $ipod->write_itunes;

B:

    my $ipod = Mac::iPod::GNUpod->new(mountpoint => '/mnt/ipod');

    $ipod->read_gnupod;

    # Etc ...

    $ipod->write_gnupod;
    $ipod->write_itunes;

However, in my tests version B runs about twice as fast as A, because the gain of speed reading the GNUpod DB far outweighs the cost of the extra write step. (Of course, the significance of this depends on what you do in the middle.)

Adding and removing songs

Add songs with add_song. Remove songs with rm_song.

Finding existing songs

You can search for existing songs on your iPod with the search method. If you want a list of all songs, use all_songs.

Working with playlists

This module can read existing playlists from your iPod and allows you to modify them in any way you want, or you can create new ones. There is also a mechanism for creating playlists that mimic the smartplaylists created by iTunes. See add_pl, get_pl and render_pl for details.

The smartplaylists created by iTunes are theoretically not touched by this module, although they cannot be modified. This feature is untested, so it is possible that this module will munge your smartplaylists.

METHODS

new

    my $ipod = Mac::iPod::GNUpod->new(mountpoint => '/mnt/ipod');

You create a new iPod object with new(). You must supply key-value pairs as arguments. Most of the time you will only provide the CWmountpoint key, which indicates where the iPod is mounted. However, if your iPod structure is nonstandard or you wish to test without writing to the actual iPod, you may provide both the CWgnupod_db and CWitunes_db keys with values indicating the locations of those files.

mountpoint

    my $mnt = $ipod->mountpoint;
    $ipod->mountpoint('/mnt/ipod2');

You may use this method to get the current mountpoint for the iPod. If you provide an argument, it sets the mountpoint. When you use this method to set the mountpoint, it automatically sets the CWitunes_db and CWgnupod_db, potentially overwriting values you may have previously had there.

itunes_db

    my $itunes = $ipod->itunes_db;
    $ipod->itunes_db('/home/ipod/testdb');

Use this method to get/set the location of the iTunes DB, if it is different from the default location on the iPod. The default location is CW{mountpoint}/iPod_Control/iTunes/iTunesDB.

gnupod_db

    my $gnupod = $ipod->gnupod_db;
    $ipod->gnupod_db('/home/ipod/gnupod.xml');

Use this method to get/set the location of the GNUpod DB, if it is different from the default location. The default location is CW{mountpoint}/iPod_Control/.gnupod/GNUtunesDB.

allow_dup

    $ipod->allow_dup(1);

Get/set the flag stating whether duplicate songs are allowed. If this is false, when you call CWadd_song, this module will check for duplicates in the DB and refuse to add the song if a duplicate is found. If true, no duplicate checking is done. Default is FALSE, which means no duplicates.

Note that this module identifies duplicates pretty stupidly, simply by comparing file size and bitrate. False positives are possible, and in your application you might want to use some other, more sophisticated method for determining if two files are duplicate. You can find out which song in the database is suspected to be a duplicate by using get_dup.

move_files

    $ipod->move_files(0);

Get/set the flag stating whether or not to actually (re)move files. If true, when you call CWadd_song or CWrm_song, the files will actually be copied or deleted. If false, the songs will simply be added or removed from the database, but the file contents of your iPod will not be changed. Default is TRUE.

init

    $ipod->init;

Initialize a blank or empty iPod. NOTE: this method only pays attention to CWmountpoint.

restore

    $ipod->restore;

Restore an iPod with corrupted databases. This scans the files on the iPod and rebuilds the databases with the files it finds. (This is equivalent to the CWgnupod_addsong.pl script with the CW--restore option.

read_itunes

    $ipod->read_itunes;

Read an iTunes database (found at CWitunes_db) into memory. Note that this will forget any iTunes or GNUpod DB previously read.

write_itunes

    $ipod->write_itunes(name => 'my iPod');

Write the contents of memory to the iTunes DB. You should do this at the end of any script if you want your newly added or deleted songs to be available when you unmount your iPod! You may pass a name argument as shown above if you want to change the name of your iPod.

Beware that when you call CWwrite_itunes() the id numbers of songs in the database may change. Data that are internal to this module are properly updated, but beware that if you have id numbers stored from before calling CWwrite_itunes() they may not still point to the song you intend.

read_gnupod

    $ipod->read_gnupod;

Read the GNUpod database into memory. This also forgets any databases previously read.

write_gnupod

    $ipod->write_gnupod;

Write the GNUpod database. If you want to use any GNUpod tools with the iPod, you should write this db at the end of any script.

add_song

    $ipod->add_song('/home/music/The Cure - Fascination Street.mp3');
    $ipod->add_song(@songs);

Add a song to the iPod. Takes one or more arguments, which are the filenames of songs to be added. Files are recognized by their extensions, so attempting to add a file with an unknown extension (or no extension) will fail. Currently only CW.mp3 and CW.wav files are supported. On success, this method returns the new id number of the song(s), on failure returns undef. Failure can mean that the file could not be copied or that duplicate files were found.

For MP3 files, metadata (artist, title, etc.) are gleaned from the ID3 tag, with preference given to ID3v2. For WAV files, data are taken from metadata encoded with Audio::Mix or from the path. If path information is used, the filename (minus extension) is taken to be title, the enclosing directory the album, and the directory above that the artist. If you wish to override the default way that metadata are gathered you can give a hash reference as the argument to this function. In this case, your hash reference must contain a CWfilename key that gives the path to the file, and the remaining keys may contain the file's metadata. Ex:

    $ipod->add_song({ filename => 'random.wav', artist => 'The Digits', album => 'Of Pi' });

You can also use this method to add custom fields to your database. Any keys you put in your hashref will be indexed for searching and written to the GNUpod database, but otherwise ignored.

get_dup

    $duplicate = $ipod->get_dup($file);

Given a filename, returns the song id of any songs believed to be duplicates of this song. Returns undef if no duplicates are found. You may use this function to double-check two songs reported to be duplicates.

rm_song

    $ipod->rm_song($id);
    $ipod->rm_song(@ids);

Remove a song from the iPod. Takes one or more arguments, which are the id numbers of the songs to be removed. (You can find the id numbers of songs using the CWsearch method.) Returns the number of songs successfully removed.

get_song

    my $song_info = $ipod->get_song($id);

Get information about a song. Takes one or more arguments, which are the id numbers of songs. Returns a hash reference (or a list of hash references) with the following keys, some of which may be undef:

* id
* artist
* album
* title
* songnum
* songs
* cdnum
* cds
* composer
* year
* genre
* fdesc
A brief description of the file type
* filesize
* bitrate
* time
Playing time in milliseconds
* srate
The frequency in hertz
* playcount
* path
The iPod-formatted path. To get a path in local filesystem format, use get_path.
* orig_path
The path to the file on the local filesystem. This key may not be available or accurate, depending on when and how this file was added to the database.

As of version 1.2, all of the values of this hash are actually Unicode::String objects. This probably will not matter because Unicode::String objects are properly overloaded for stringification. However, if you have other data not in Unicode, you may want to use the proper method from Unicode::String to get the data in the encoding you're expecting.

get_path

    $path = $ipod->get_path($id);

Get a path formatted by local filesystem conventions. Takes a list of ids as arguments, returns a list of paths to the songs with those ids. If CWmountpoint isn't set, returns undef.

BUG WARNING: If you try to get the path of a song that was added while CWmove_files was false, you will probably get garbage.

search

    my @ids = $ipod->search(artist => 'Bob Dylan', title => 'watchtower', nocase => 1);

Search for songs on the iPod. The argument to this function is a hash of key => value pairs that give attributes that the returned songs will match. You may search on any of the keys that appear in the hashref returned from CWget_song (listed above). You may specify multiple keys, in which case the songs returned must match ALL of the values specified. By default, searches are regexes, which means that searching for CWartist => 'Cure' will return songs labeled 'Cure', 'The Cure', 'Cure, The', and 'Cured!' You may also use regex metacharacters in your values, like CWtitle => '[Tt]he', or even precompiled regexes created with qr//. A list of id numbers is returned, which can be used with CWget_song to get the complete information about a song.

You may also alter the behavior of the search by using special hash keys. These keys are:

* exact
Only return songs that match the given terms EXACTLY. This tests using CWeq instead of a regular expression, and so is much faster.
* nocase
Perform a case-insensitive search. This is not mutually exclusive with CWexact; using both of them searches for things that are identical except with regard to case.
* nometachar
Ignore regular expression metacharacters in the values given. (Redundant when used with CWexact.)

The search results are returned to you sorted by Artist > Album > Cdnum > Songnum > Title.

all_songs

    my @songs = $ipod->all_songs;

Return a list of the id's all of the song ids on the iPod.

add_pl

    $ipod->add_pl($name, @songs);

Adds a playlist to the iPod. The first argument to this function should be the name of the playlist to be added, and the remaining arguments either the id's of the songs in that playlist or a hash reference. If you give a hash reference as one of the arguments, the hash should consistof key => value pairs just like ones you would pass to search. When you do this, the ids of the songs matching your search terms will be inserted into the playlist when you call write_itunes, similar to what happens when you use smartplaylist in iTunes.

For example, the following creates a playlist with the songs numbered 3, 7, and 15:

    $ipod->add_pl("playlist 1", 3, 7, 15);

This example creates a playlist with song 3, all songs with the artist 'foo', and then song 15:

    $ipod->add_pl("playlist 2", 3, { artist => 'foo' }, 15);

get_pl

    my $pl = $ipod->get_pl($name);
    my @pls = $ipod->get_pl(@names);

Gets an array reference to the playlist given by CW$name, or CWundef if no such playlist exists. The elements of the array reference are the same as the arguments given to add_pl, either id numbers or hash references which can be passed to search to get id numbers. To find out what a playlist will look like when all of the hash references are expanded, use render_pl.

render_pl

    my @ids = $ipod->render_pl($name);

Get a list of the songs in playlist CW$name after all of the hash references in that playlist are expanded. This will give you exactly the songs as they will appear when you call write_itunes.

all_pls

    @pls = $ipod->all_pls;

Returns an array of the names of all playlists currently in the iPod.

rm_pl

    $ipod->rm_pl($name);
    $ipod->rm_pl(@names);

Removes a playlist from the ipod. Returns the number of playlists actually deleted.

get_spl

    my $spl = $ipod->get_spl($name);
    my @spls = $ipod->get_spl(@names);

Gets a hash reference describing the smartplaylist given by CW$name, or CWundef if no such smartplaylist exists. The format of the hash reference returned is not documented and should not be touched.

NOTES

The GNUpod XML file is expected to be encoded in UTF-8. Other encodings will probably work as well (UTF-16 has been tried successfully), but Your Mileage May Vary.

Playlists that contain <add /> elements that don't have id attributes, <regex /> elements, or <iregex /> elements may produce songs in a different order than the order produced by the GNUpod script mktunes.pl. This is because mktunes.pl simply adds matching songs to the playlist in the order that it finds them, while this module sorts them by artist, album, cdnum, tracknum, and title. What the module does is better :).

TODO

Add support for more filetypes, particularly .m4a/.mp4 files.

BUGS

Smartplaylist support is untested, so it's entirely possible that this module will munge your smartplaylists (though it tries not to).

Turning CWmove_files on and off during the life of an object may have strange side effects. If you only set it once at the beginning of the script, you'll be safe.

AUTHOR

Original GNUpod scripts by Adrian Ulrich <pab at blinkenlights.ch>. Adaptation for CPAN, much code rewriting, and expansion by JS Bangs <jaspax@cpan.org>.

VERSION

v. 1.2, Jan 09 2004.

LICENSE

The GNUpod scripts are released under the GNU Public License (GPL). This module adaptation is released under the same terms as Perl itself (a conjunction of the GPL and the Artistic License).

iTunes and iPod are trademarks of Apple. This module is neither written nor supported by Apple.