MP3::Napster - Perl interface to the Napster Server


NAME

MP3::Napster - Perl interface to the Napster Server


SYNOPSIS

  use MP3::Napster;
  my $nap = MP3::Napster->new;
  # log in as "username" "password" using a T1 line
  $nap->login('username','password',LINK_T1) || die "Can't log in ",$nap->error;
  # listen for incoming transfer requests on port 6699
  $nap->port(6699) || die "can't listen: ",$nap->error;
  # set the download directory to "/tmp/songs"
  mkdir '/tmp/songs',0777;
  $nap->download_dir('/tmp/songs');
  # arrange for incomplete downloads to be unlinked
  $nap->callback(TRANSFER_DONE,
                 sub { my ($nap,$code,$transf) = @_;
                       return unless $transf->direction eq 'download';
                       return if $transf->status eq 'transfer complete';
                       warn "INCOMPLETE: ",$transf->song," (UNLINKING)\n";
                       unlink $transf->local_path; 
                      } );
  # search for songs by the Beatles that are on a cable modem or better
  # and have a bitrate of at least 128 kbps
  my @songs = $nap->search(artist=>'beatles',linespeed=>LINK_CABLE,bitrate=>128);
  # initiate downloads on the first four songs
  my $count = 0;
  foreach my $s (@songs) {
    next if $seen_it{$s}++;
    next unless $s->owner->ping;
    next unless $s->download;  # try to initiate download
    print "Downloading $s, size = ",$s->size,"\n";
    last if ++$count >= 4;  # download no more than four
  }
  # disconnect after waiting for all pending transfers to finish
  $nap->wait_for_downloads;
  $nap->disconnect;


DESCRIPTION

MP3::Napster provides access to the Napster MP3 file search and distribution protocol. With it, you can connect to a Napster server, exchange messages with users, search the database of MP3 sound files, and either download selected MP3s to disk or pipe them to another program, typically an MP3 player.

The module can be used to write Napster robots to search and download files automatically, or as the basis of an interactive client.


THEORY OF OPERATION

The Napster protocol is asynchronous, meaning that it is event-oriented. After connecting to a Napster server, your program will begin receiving a stream of events which you are free to act on or ignore. Examples of events include PUBLIC_MESSAGE, received when another user sends a public message to a channel, and USER_JOINS, sent when a user joins a channel. You may install code subroutines called ``callbacks'' in order to intercept and act on certain events. Many events are also handled internally by the module. It is also possible to issue a command to the Napster server and then wait up to a predetermined period of time for a particular event or set of events to be returned.

If you wish to build an interactive Napster client on top of this module, you will need to install a series of callbacks to handle each of the events that you wish to catch. Once the callbacks are installed, you will call the run() method in order to run MP3::Napster's event loop. run() will not return until the connection between client and server is finished. To process line-oriented user commands during this time, you can install a command-handling callback using the command_processor() method.

MP3::Napster has a Tk mode, for writing applications on top of the graphical PerlTk module. In this mode, Tk takes over MP3::Napster's internal event loop, processing I/O from the server and peers, and invoking your callbacks when appropriate.

You don't need to worry about callbacks if you only intend to use the module as a non-interactive robot.

Because of its asynchronous operation MP3::Napster makes heavy use of nonblocking I/O and Perl's IO::Select class. IO::Select is standard in Perl versions 5.00503 and higher. Other prerequisites are Digest::MD5 and MP3::Info (both needed to handle MP3 uploads).

The Napster protocol has a peer-to-peer component. During MP3 upload and download operations between two users, one user's client will initiate a connection to the other. In order for such a connection to succeed, at least one of the clients must be listening for incoming connections on a network port. The MP3::Napster module can do this, either by listening on a hard-coded port, or by selecting a free port automatically. If you are behind a firewall and cannot make a port available for incoming connections, MP3::Napster will be able to exchange files with non-firewalled users, but not with those behind firewalls.

For more information on the Napster protocol, see opennap.sourceforge.net, or the file ``napster.txt'' which accompanies this module. This file contains a partial specification of the Napster protocol, as reverse engineered by several Open Source developers.


BASIC OPERATION

This section describes the basic operation of the module.

Connecting, Disconnecting, and Retrieving Errors

$nap = MP3::Napster->new([$address])
$nap = MP3::Napster->new(@options)
The new() class method will attempt to establish a connection with a Napster server. If you wish to establish a connection with a particular server, you may provide its address and port number in the following format: aa.bb.cc.dd:PPPP, where PPPP is the port number. You may use a hostnames rather than IP addresses if you prefer.

If you do not provide an address, MP3::Napster will choose the ``best'' server by asking the ``meta'' Napster master server located at server.napster.com:8875. Note that there are several Napster servers, and that a user logged into one server will not be visible to you if you are logged into a different one.

If successful, new() return an MP3::Napster object. Otherwise it will return undef and leave an error message in $@ and in MP3::Napster->error.

The module also provides a long form of the new() method which takes a series of option/value pairs. Options and their defaults are:

 Option    Description                   Default
 -server   Server in form addr:port      undef
 -meta     Metaserver in form addr:port  server.napster.com:8875
 -tkmain   TK main widget                undef

The -server argument has the same meaning as in the single-argument form of new(). -meta allows you to specify an alternative address for the Napster meta server. -tkmain provides a hook into the Perl-Tk event handling, as described below under Using MP3::Napster with PerlTk. For example, to connect to the BitchX server and use the Tk event handling system:

  use Tk;
  use MP3::Napster;
  $main = MainWindow->new;
  $nap  = MP3::Napster->new(-server => 'bitchx.dimension6.com:8888',
                            -tkmain => $main);

$nap->disconnect([$wait])
The disconnect() object method will sever its connection with the Napster server and tidy up by cancelling any pending upload or download operations.

By default, disconnect() will immediately abort all pending downloads
and uploads.  If you wish your script to wait until they are done,
call wait_for_downloads() first.

$nap->wait_for_downloads
This method will block until all pending uploads and downloads are complete. It first unshares all shared files, and refuses to service new upload requests.

In the case of a slow or hung peer, wait_for_downloads() will wait until the transfer has timed out, ordinarily five minutes of complete inactivity. See Waiting for Downloads for details on how to alter this.

$nap->run
Run the event loop, receiving and responding to events. This operation will block until the connection is disconnected. Ordinarily, you will disconnect the connection within a callback.

$nap->error
The error() method will return a human-readable string containing the last error message to be emitted by the server or generated internally by MP3::Napster. You may clear the error message by setting it to an empty string this way:
  $nap->error('');

If multiple errors occur in quick succession, error() will return only the most recent one.

Login and Registration

After establishing a connection with a Napster server, you must either login as an existing user, or register as a new one. The methods in this section provide access to the login facilities.

$email = $nap->login($nickname,$password [,LINK_SPEED] [,$port])
The login() method will attempt to log you in as a registered user under the indicated nickname and password. You may optionally provide a link speed and a value describing the port on which the client will accept incoming connections.

The link speed should be selected from the following list of exported constants:

  LINK_14K   LINK_64K    LINK_T1
  LINK_28K   LINK_128K   LINK_T3
  LINK_33K   LINK_CABLE  LINK_UNKNOWN 
  LINK_56K   LINK_DSL

The link speed will default to LINK_UNKNOWN if absent. The indicated speed will be displayed to other users when they browse your list of shared files and user profile.

The port many be any valid internet port number, normally an integer between 1024 and 65535. The standard napster port is 6699, but you are free to use any valid port. If a port of 0 is specified, the module will identify your client to the server as being firewalled. The module will still be able to perform file transfers by making outgoing connections to other peers, but will not be able to exchange files with other firewalled peers. If a port of -1 is specified, the module will pick an unused port automatically. This is recommended for multiuser systems.

If successful, login() will either return the email address you provided at registration time or the anonymous email address ``anon@napster.com'' if the account is not formally registered. Otherwise an undefined value will be returned and the error message left in $nap->error. Typical errors include ``no such user'' and ``invalid password''.

The nickname you logged in under is available as $nap->nickname.

$email = $nap->register($nickname,$password,\%attributes)
The register() method will attempt to register you as a new user under the indicated nickname and password. You may optionally provide register() with a hash reference containing one or more of the following keys:
  key        description
  ---        -----------
  link       Link speed, selected from among the LINK_* constants
  port       Preferred port for incoming connections
  email      Your e-mail address
  name       Your full name
  address    Your street address
  city       Your city
  state      Your state (two-letter abbreviation)
  phone      Your phone number
  age        Your age
  income     Your income level
  education  Your educational level

Of these attributes only the link speed is relevant, since the others can either be automatically determined by the module, or may be considered intrusive by some people. In addition, I have been unable to confirm that the demographic attributes actually ``take,'' since the uploaded information is not made available to clients.

If successful, the registration email address will be returned. Otherwise undef will be returned and $self->error will show the exact error message. Typical error messages are ``user already registered'' and ``invalid nickname.''

$result = $nap->change_registration(email=>$mail,password=>$pass,link=>$link)
Change_registration() allows you to change some fields in your registration record. Pass it one or more of the keys ``email'', ``password'' or ``link'' to change the indicated attribute.

There is no acknowledgement from the server, and therefore no positive way to confirm that the changes occurred. Indeed, there seem to be synchronization problems among the Napster servers, so that a password change on one server may not take effect on others! Therefore, use this method with care.

Sharing Files

Once you have logged in, you may begin sharing files with other users. If you choose not to do this, you may still download files and use other features of the Napster server.

$share = $nap->share('path/to/a/file.mp3' [,$cache])
The share() method will mark an MP3 file as shared with the community. The file may be specified using an absolute or relative path. However, it must be a bona fide MP3 file. MP3::Napster will use MP3::Info to determine the file's bitrate, play length and other information, and upload this information to the Napster server.

Rather than providing the Napster server with the file's full file pathname, MP3::Napster constructs a ``share name'' based on the file's IDv3 tag. For example, the song ``A Hard Day's Night'' by the Beatles will be shared under the name:

  [The Beatles] A Hard Day's Night.mp3

If the IDv3 tag is missing, the file is shared under its physical filename after stripping off the path information.

If successful, the method returns an MP3::Napster::Song object, which when used in a string context returns its share name (see the MP3::Napster::Song manpage for more details). Otherwise the method returns undef and leaves the error message in $self->error.

If you provide an optional $cache flag of true, then the IDv3 tag information will be cached in a directory named ``.mpeg-nap'' parallel to the downloaded file. This avoids having to collect statistics on the file every time you share it. This is recommended if you frequently share large numbers of files. However, it requires that the directory containing the indicated file be writable and executable.

@shares = $nap->share_dir('path/to/a/directory/' [,$cache])
This is like share() but instead of sharing a single file it shares the contents of a directory, and returns the list of MP3::Napster::Song objects shared in this way. Currently, the module does not automatically monitor the directory and add to the list of shares when it is updated.

$port = $nap->port([$port])
The port() method will set or change the port on which the client listens for incoming connections. This method is called internally by login() and register() immediately after the client successfully logs into the server. You may call the method at any time thereafter in order to change the port, or to disable incoming connections.

You may hard-code a port to listen to and provide it as an argument to listen(). If you provide a negative port number, port() will select an unused high-numbered port and register it with the Napster server. This is recommended if you are on a machine that is shared by multiple users and there are no firewall issues that will limit the range of open ports. The standard port used by the PC clients is 6699.

Called with no arguments, this method returns the current port.

Note that it is possible for a Napster server to tell the module to change its data port number. Install a callback for the CHANGE_DATA_PORT event if you want to be notified when this happens. Set allow_setport() to a false value to prevent this from happening.

If you are behind a firewall and cannot accept incoming connections, set the port to 0, or just accept the defaults. This will inform the Napster server that you are firewalled. Although you will not be able to exchange files with other firewalled users, you will be able to do so with non-firewalled users.

If successful, port() returns the port that it is listening on. Otherwise it returns undef and leaves the error message in $nap->error. Uploads requested by remote users will proceed automatically without other intervention. You can receive notification of these uploads by installing callbacks for the TRANSFER_STARTED, TRANSFER_IN_PROGRESS and TRANSFER_DONE events or by interrogating the $nap->uploads() method (described below).

$flag = $nap->allow_setport([$flag])
The Napster protocol allows the server to send the client SET_DATA_PORT commands, causing the module to change the port that it is listening on. This may be a security hole, because it allows unscrupulous individuals to open arbitrary listening ports on your machine, so by default, the module ignores such requests. To turn automatic handling of setport messages on, call allow_setport() with a true flag.

Without any arguments, the method returns the current state of the flag.

item $song->unshare()

Given a Song object returned from share() or share_file(), unshare() will unregister the song, removing it from the search list at the server and disallowing further downloads.

Searching and Downloading Song Files

You may search the Napster sound file directory by keyword search, or by browsing all the files shared by a named user. The search functions return a list of matching MP3::Napster::Song objects, each of which contains such information about the song as its bitrate, its length, and its sample frequency. You can download a desired song either by invoking its download() method directly (see the MP3::Napster::Song manpage) or by passing the song to the MPEG::Napster object's download() method. Also see the MP3::Napster::User manpage for information on how to determine whether the owner of a song is still online and reachable.

@songs = $nap->browse($nickname)
The browse() method returns a list of the song files shared by a user. You may provide the user's nickname or a MP3::Napster::User object as the argument. The method will return a list of songs shared by the user, or an empty list. The empty list will be returned when the user is online but sharing no files as well as in such exceptional conditions as the user being offline or nonexistent. You can distinguish between the two cases by checking $nap->error.

@songs = $nap->search('keywords')
@songs = $nap->search(%attributes)
The first form of the search() method allows you to search for songs by words located in the artist's name or the song title. For example, this will search for Bob Dylan's Blowing in the Wind:
 @songs = $nap->search('bob dylan blowing in the wind');

For unknown reasons, lowercase searches are more effective than uppercase ones. The result value is an array of matching songs, or an empty list if none were found.

A more structured search can be made by providing search() with a hash of attribute/value pairs. The available attributes are as follows:

  Attribute        Value
  ---------        -----
  artist           The artist's name
  title            The song title
  limit            Limit the responses to the indicated number
  linespeed        The link speed of the owner
  bitrate          The bitrate of the song, in kbps
  frequency        The sampling frequency of the song, in Hz

The linespeed, bitrate and frequency fields can be specified in any of the following forms:

 Form                     Example
 ----                     -------
 1. a bare value          bitrate => 128
 2. "at least $value"     bitrate => 'at least 128'
 3. "at best $value"      bitrate => 'at best 64'
 4. "equal to $value"     frequency => 'equal to 44100'

Using a bare value is the same as specifying ``at least''.

In this example, we search for songs by Bob Dylan that have a bitrate of at least 160 kbps and are sampled at exactly 44.1 kHz:

  @songs = $nap->search(artist => 'Bob Dylan',
                        title  => 'Blowing in the Wind,
                        bitrate => 160,
                        frequency => 'equal to 44100');

Due to server limitations, ``artist'' and ``title'' are interchangeable, and ``limit'' doesn't seem to do anything. Search results are limited to 100 songs at the server's end of the connection. No facility is provided for searching on a song's size or play length.

$path = $nap->download_dir( [$path] )
The download_dir() gets or sets the path to the directory used for automatic downloads. If a song download is initiated without providing an explicit path or filehandle, the song data will be written into a file having the same name as the song located in the directory indicated by download_dir().

Download_dir() starts out containing the empty string, which will cause the song data to be written to the current working directory. You may change the path by providing the method with an argument containing a relative or absolute directory. For example:

  $nap->download_dir('/tmp/songs');  # write data to this path

The download directory must already exist. It will not be created for you.

$download = $nap->download($song [, $file | $fh ])
Given an MP3::Napster::Song object returned from a previous search() or browse(), the download() method will attempt to initiate a download and perform the file transfer in the background. If the download is successfully initiated, an MP3::Napster::Transfer object will be returned (see the MP3::Napster::Transfer manpage). You can use this object to monitor the progress of the transfer. If the download attempt was unsuccessful, the method will return undef and leave an error message in $nap->error.

You may also monitor the progress of the transfer by installing callbacks for TRANSFER_STARTED, TRANSFER_IN_PROGRESS, and TRANSFER_DONE, as described later.

The download() method takes an optional second argument that can be either a file path or a filehandle. In the case of a file path, the file is opened for writing. If the file already exists, it is opened for appending and the download is coordinated in such a way that only the portion of the local file that is missing is downloaded from the peer. This can be used to resume from previously cancelled download attempts.

If you pass a filehandle to the download() method, the song data will be written directly to the filehandle. This will work for pipes and other types of handles as well as with filehandles. For example, you can play a song directly off the net by opening up a pipe to your favorite command-line MP3 decoder.

   open(PLAYER,"|mpg123 -");
   $nap->download($song,\*PLAYER);

You must pass filehandles as GLOB refs (\*FH), GLOBS (*FH) or as IO::Handle objects.

If no path or filehandle is passed to download(), then the module will write the song data into a file having same name as the song located within the directory specified by the download_dir() method.

@downloads = $nap->downloads
@uploads = $nap->uploads
@transfers = $nap->transfers
The downloads() method will return the list of active MP3::Napster::Transfer objects being used for downloading. If the download has already completed, it will not be present on this list.

The uploads() method returns all pending uploads, and transfers() returns the union of downloads() and uploads().

See the MP3::Napster::Transfer manpage for more information on managing downloads, including how to abort them prematurely.

Chat Groups and Users

These methods provide access to Napster's chat groups, which are also known as ``channels''. To capture public and private messages, you must install callbacks for the relevant events. See Callbacks.

@channels = $nap->channels
The channels() method will return a list of available channels as an array of MP3::Napster::Channel objects. When used in a string context, these objects interpolate as the name of the channel. Object methods provide access to the topic channel, the number of users on the channel, and to the list of the users currently participating in the channel. The channel object also provides a join() method that will allow you to join it and start receiving its events.

See the MP3::Napster::Channel manpage.

$result = $nap->join_channel($channel)
The join_channel() method will join the indicated channel. You may provide an MP3::Napster::Channel object from a previous channels() call, or a plain string containing the name of the channel.

After joining a channel, the client will begin to send event messages relevant to the channel, such as notifications of when users join or leave the channel. This method also sets the user's ``current channel'', which is used as the default destination for the public_message() method.

More than one channel can be joined simultaneously, up to a limit set by the server. If the channel is joined successfully, a true result will be returned. Otherwise undef will be returned and $nap->error will contain the error message. The list of channels currently joined can be retrieved with the member_channels() method. If you attempt to join the same channel more than once, join_channel() will have the effect of making the selected channel the current one.

$result = $nap->part_channel($channel)
The part_channel() method will disconnect you from the indicated channel so that you no longer receive messages from the channel. You may pass the method an MP3::Napster::Channel object,or just a plain string containing the channel name. The method always returns a true value, since the server provides no positive acknowledgement that the channel was successfully departed.

$channel = $nap->channel([$channel])
The channel() method will return the current channel object, or undef if no channel is current. It can also be used to set the current channel to the one indicated by the argument. However it is better to use join_channel() for this purpose.

@channels = $nap->enrolled_channels
This method returns the list of channels in which the user is currently enrolled, or an empty list if the user is not enrolled in any.

@users = $nap->users([$channel])
The users() method returns the list of users currently attached to the channel as an array of MP3::Napster::User objects. User object methods allow you to ping the indicated user, discover a limited amount of information about him or her, and list his or her files.

If you provide a channel name or object, the user list will be retrieved from that channel. Otherwise the method returns the list of users enrolled in the current channel.

In case of error, the methods returns an empty list and stashes the error message in $nap->error.

$result = $nap->public_message($message [,$channel])
This method sends a public message to the indicated channel, or the current channel if one is not designated. On success, the method returns a true result. On failure, it returns undef and sets $nap->error to a pithy error message.

I do not know whether there is a limit on the size or content of public messages. Most messages posted to the Napster service are short single lines containing cryptic abbreviations and poorly-disguised obscenities.

$result = $nap->private_message($nickname,$message)
Private_message() sends a private message to the indicated user. You may provide an MP3::Napster::User object, or just the user's nickname as a string. On success, the method returns a true result. On failure, it returns undef and sets $nap->error to an error message.

I do not know whether there is a limit on the size or content of private messages. Most messages posted to the Napster service are short single lines.

$user = $nap->whois($nickname)
Given a string containing the nickname of a user, whois() returns an MP3::Napster::User object which you can query for further information on the user. On an error, this method returns undef and sets $nap->error. The most typical error is ``no such user''. If the user is offline, you will receive an object whose fields are mostly blank. See the MP3::Napster::User manpage.

$result = $nap->ping($nickname [,$timeout])
Given a string containing the nickname of a user or a MP3::Napster::User object and an optional timeout value in seconds, ping() sends a ping message to the user's client to determine if he or she is online. If the user's client responds within the indicated period of time, then the method returns true.

This method is also accessible directly from the MP3::Napster::User object.

If timeout is explicitly set to zero, then the routine will return immediately without waiting for the reply. You may intercept the PONG event with a callback in order to calculate the round-trip time to the remote user.

($users,$files,$gigabytes) = $nap->stats
The stats() method returns a three element list containing server statistics. The elements of the list are the number of users currently logged in, the number of song files being shared, and the total number of gigabytes of the shared files.

Statistics messages (event SERVER_STATS) are issued by the Napster server at more-or-less random intervals. If no statistics event has arrived, this method will block until one does. This is not usually a problem as the first statistics event arrives soon after login.

Low-Level Functions

Some low-level functions are documented. Others are for internal use and shouldn't be relied upon. Caveat emptor!

$result = $nap->send($event_code,$message)
This method will send the indicated event code and message to the server, and will return a result code indicating whether the message was sent successfully (but not whether it was in the correct format or correctly processed!)

For a list of event codes, see Outgoing Events below. For the exact format of the message to send, see the napster.txt document that accompanies the MP3::Napster distribution.

Example:

  $nap->send(PING,"Poppa_Bear");

($event,$message) = $nap->wait_for(\@event_codes [,$timeout])
The wait_for() method will block until one of the indicated events occurs or the call times out, using the optional $timeout argument (expressed in seconds). If one of the events occurs, wait_for() will return a two-element list containing the event code and the message. If the call times out, the method will return an empty list.

wait_for() provides a number of shortcut variants. To wait for just one event, you can pass the event code as a scalar rather than an array reference. If you call the method in a scalar context, it will return just the event code, discarding the message, or undef in the case of a timeout.

Example 1:

  $nap->send(PING,"Poppa_Bear");
  if ( ($ec,$msg) = $nap->wait_for(PONG,20) ) { # wait 20 seconds
     print "Got a PONG from $msg\n";
  } else {
     print "PING timed out\n";
  }

Example 2:

  $nap->send(PING,"Poppa_Bear");
  $ec = $nap->wait_for([PONG,NO_SUCH_USER],20);
  if ($ec == PONG) {
     print "Got a PONG\n";
  } elsif ($ec == NO_SUCH_USER) {
     print "No such user!\n";
  } else {
     print "Timed out\n";
  }

($event,$message) = $nap->send_and_wait($event_code,$message,\@event_codes [,$timeout])
This method combines send() with wait_for() in one operation.

Example:

  ($ec,$msg) = $nap->send_and_wait(PING,"Poppa_Bear",[PONG,NO_SUCH_USER],20);
  if ($ec == PONG) {
     print "Got a PONG from $msg\n";
  } elsif ($ec == NO_SUCH_USER) {
     print "Invalid user: $msg\n";
  } else {
     print "Timed out\n";
  }

If timeout is explicitly set to zero, then no wait will be performed and this call will be equivalent to send().

$result = $nap->process_message($event_code,$message)
If you wish to insert an event of your own making into the event queue, process_message() allows you to do so. This will block until all callbacks for the event have finished execution.

Waiting for Downloads

Because file transfers occur in the background, you have to be careful that your script does not quit while they are still in progress. The easiest way to do this is to call wait_for_downloads(). This will unshare all shared songs to prevent further transfers from being initiated and then block until the last transfer is finished. During this time, the callbacks installed for TRANSFER_IN_PROGRESS and TRANSFER_DONE will be executed as usual.

If you prefer, you can manually check and wait on pending transfers. You might want to do this, for instance, if you want to wait for downloads, but don't care about interrupting pending uploads. This code fragment illustrates the idiom:

  # wait for the downloads to complete
  while (@d = $nap->downloads) {
    warn "waiting for ",scalar(@d)," downloads to finish...\n";
    my ($event,$download) = $nap->wait_for(TRANSFER_DONE);   
    warn "$download is done...\n";
  }

This is a loop that fetches the list of downloads currently in progress by calling the downloads() method. If it is non-empty, then there are still downloads in progress. The code prints out a warning message, and then performs a wait_for() for a TRANSFER_DONE event. When wait_for() returns, the second item in the result list is the affected MP3::Napster::Transfer object. The code prints out the Transfer object (which interpolates the song name as a string), and goes back to looping. When all the downloads are done, downloads() will return an empty list and the loop will finish.

You might want to modify this code to print out the status of finished downloads and to unlink incomplete song files. It is also possible to abort a pending download by calling its abort() method (see the MP3::Napster::Transfer manpage). See the napster.pl and eg/simple_download.pl scripts for some ideas on doing this.

Similar code will also work for pending uploads.

To time out the process of waiting for transfers to complete, you can use a standard eval{} block:

  eval {
     alarm(300);  # allow five minutes for completion
     local $SIG{ALARM} = sub { die "timeout" };
     $nap->wait_for_downloads();
  }
  alarm(0);

You may also adjust an internal timeout used for idle transfers:

$timeout = $nap->transfer_timeout([$timeout])
Internally the module checks transfers at regular intervals and cancels any that have been inactive for a period of time. Inactivity means that no data has been transmitted in either direction.

The default timeout is 300 seconds (five minutes). You may examine and change this value with the transfer_timeout() method.


CALLBACKS

If you wish to write an interactive Napster client based on this module, you will need to intercept and act on at least some of the server events that are issued asynchronously after you login. You do this by installing callbacks, which are simply Perl code references associated with certain event codes. Once a callback is installed, the subroutine is invoked whenever the corresponding event occurs. An event can have multiple callbacks installed, or no callbacks at all.

Callback Methods

The callback() and replace_callback() methods allow you to attach and remove callbacks from events.

$coderef = $nap->callback(EVENT_CODE [,$coderef])
The callback() method assigns a callback subroutine to an event. The event code is a small integer constant that is imported by default when you load MP3::Napster. See Incoming Events for the listing of event codes. It is possible to have several callbacks assigned to a single event. The subroutines will be called in the reverse order of which they were assigned.

The two-argument form appends a callback to the event. With a single argument, callback() returns the list of callbacks currently assigned to the event.

$nap->replace_callback(EVENT_CODE [,$coderef])
The replace_callback() method assigns a callback to the indicated event code, replacing whatever was there before. When called with a single event code argument, any callbacks assigned to the event code are deleted.

$nap->delete_callback(EVENT_CODE [,$coderef])
The delete_callback() method deletes a callback from the indicated event code. If called without a code reference, all callbacks assigned to the event are cleared. Use this with caution, as some callbacks are used internally to handle transfer requests.

$event_code = $nap->event_code
The event_code() method returns the current event code. It is most useful when called from within a callback subroutine to determine what event triggered the callback.

$event_code = $nap->event_code
The event_code() method returns the current event code. It is most useful when called from within a callback subroutine to determine what event triggered the callback.

$event = $nap->event
The event() method returns the current event as the string corresponding to the event code constant. For example, the USER_JOINS code, numeric 406, will be returned by $nap->event_code as numeric 406, and as ``USER_JOINS'' by $nap->event.

$message = $nap->message($code [,$msg])
The message() method returns the message associated with the specified event code. It can also be used to change the message. This method is most useful when used from within a callback.

When a callback is invoked, it is passed three arguments consisting of the MP3::Napster object, the event code, and a callback-specific message. Usually the message is a string, but for some callbacks it is a more specialized object, such as an MP3::Napster::Song. Some events have no message, in which case $msg will be undefined.

Callbacks should have the following form:

 sub callback {
    my ($nap,$code,$msg) = @_;
    # do something
 }

Here's an example of installing a callback for the USER_JOINS event, in which the message is an MP3::Napster::User object corresponding to the user who joined the channel:

 sub report_join {
   my ($nap,$code,$user) = @_;
   my $channel = $user->current_channel;
   print "* $user has entered $channel *\n";
 }
 $nap->callback(USER_JOINS,\&report_join);

The same thing can also be accomplished more succinctly using anonymous coderefs:

 $nap->callback(USER_JOINS,
                sub {
                    my ($nap,$code,$user) = @_;
                    my $channel = $user->current_channel;
                    print "* $user has entered $channel *\n";
                });

Callbacks are invoked in an eval() context, which means that they can't crash the system (hopefully). Any error messages generated by die() or compile-time errors in callbacks are printed to standard error.

Handling User Input

If you wish to write an interactive application that takes user input and passes it on to the Napster server, MP3::Napster provides a way to monitor a filehandle for available data and invoke a callback whenever there is a complete line to read.

$nap-command_processor($coderef [,$filehandle])>
The command_processor will install the code reference $coderef to be called whenever $filehandle has a complete line of data to be read. If no filehandle is provided, then STDIN is assumed.

Here is an example of using this facility:

 $nap->command_processor(\&do_command,\*STDIN);
 $nap->run;
 sub do_command {
   my $nap  = shift;
   my $line = shift;
   if ($line =~ /^login/) {
      do_login($line);
   } elsif ($line =~ /^whisper/) {
      do_whisper($line);
   }
 }

This example first installs do_command() as the handler for data coming in on STDIN, and then calls $nap->run, starting the event loop. Whenever there is a complete line to read the callback will be called with two arguments consisting a reference to the MP3::Napster object, and the input line. The line may end with a terminating newline. On end of file, the callback will be called a final time with undef as the second argument.

The more traditional way of doing this will not necessarily work satisfactorily:

  while (my $line = <>) {
   if ($line =~ /^login/) {
      do_login($line);
   } elsif ($line =~ /^whisper/) {
      do_whisper($line);
   }
  }

The problem is that the program spends most of its time waiting on STDIN. During this time, background processing of file transfers and other events will not be executed.

Using MP3::Napster with PerlTk

If you wish to use MP3::Napster with PerlTk, call MP3::Napster->new() with a -tkmain argument, providing it with the reference to the main window returned by the Tk::MainWindow() function. This will change MP3::Napster's event processing in the following fundamental ways:

  1. Outgoing message methods will return immediately.
    login(), register(), search() and all the other methods that send messages to the server will no longer wait for a result, but will return immediately. The return value will indicate only whether the message was successfully queued for transmission. You must detect the result of the command by intercepting and handling events returned by the server.

  2. The run(), wait_for(), and send_and_wait() methods return immediately
    Similarly, these methods no longer block until an event has occurred but return immediately.

  3. Tk's MainLoop handles I/O
    All I/O is handled through Tk's internal event handling, by using Tk::fileevent() to install a set of filehandles to be monitored for I/O. You must call MainLoop() in order for anything to happen.

A very very primitive PerlTk interface to MP3::Napster can be found in the top level of the MP3::Napster directory in tknapster.pl. It is installed automatically in /usr/local/bin during ``make install''.

Incoming Events

This is a list of the events that can be intercepted and handled by callbacks. Those that are marked as ``used internally'' may already have default callbacks installed, but you are free to add your own using callback(). However be careful before using replace_callback() or delete_callback() to remove the default handler, and be sure you know what you're doing!

Not all of the known events are documented here (but will be in later versions). In addition, there are a number of events whose significance is not yet understood by those reverse engineering the Napster protocol.

ERROR (code 0)
  Message: <error string>

This is an error message from the server, ordinarily handled internally by remembering the error text for retrieval by the error() method.

LOGIN_ACK (code 3)
  Message: <email address>

Acknowledgement of a successful login attempt. Usually handled internally by the login() and register() methods.

REGISTRATION_ACK (code 8)
  Message: none

Server acknowledges a successful registration attempt. Ordinarily handled internally by register().

ALREADY_REGISTERED (code 9)
 Message: none

Registration has failed because the nickname is taken. Ordinarily handled internally by register().

INVALID_NICKNAME (code 10)
  Message: none

Registration has failed because the nickname is invalid. Ordinarily handled internally by register().

LOGIN_ERROR (code 13)
   Message: <error string>

Some error occurred during login (such as invalid password). Ordinarily handled internally by login().

SEARCH_RESPONSE (code 201)
  Message: MP3::Napster::Song

This event is returned in the course of a search to indicate a matching song. The event is the MP3::Napster::Song corresponding to the search result. There will be one such events for each song that is matched. You might want to stuff the result into a global array in order to build up a list of such responses. This is ordinarily handled internally by the search() method.

SEARCH_RESPONSE_END (code 202)
  Message: none

This event is returned at the end of a search to indicate that it is done. This is ordinarily handled internally by the search() method.

DOWNLOAD_ACK (code 204)
  Message: <nick> <ip> <port> "<filename>" <md5> <linespeed>

This event is sent by the server to acknowledge your request for a download (event DOWNLOAD_REQ). The message is a string containing multiple fields. See napster.txt in the MP3::Napster distribution for details. This event is ordinarily handled internally by the download() method.

PRIVATE_MESSAGE (code 205)
  Message: <nick> <msg>

User has sent you a private message. The message is a string containing the fields <nick> and <msg> separated by a single space. You can parse it out with the regular expression /^(\S+) (.*)/

This event is ordinarily ignored.

GET_ERROR (code 206)
  Message: <nick> "<filename>"

The file requested for download from user <nick> is unavailable. The message is a string containing the user's nickname and the requested file path, enclosed in quotes. For example:

        lefty "C:\stuff\mp3\John Phillips Sousa - Oh Canada!"

This condition is usually handled internally by the download() method.

USER_SIGNON (code 209)
  Message: <nick> <link>

A user on your hotlist has logged on to the server. The message consists of the user's nickname and a small integer indicating the user's link speed, separated by a space.

Hotlists are not currently implemented in the MP3::Napster API. This message will probably be converted into an MP3::Napster::User object in the final version.

USER_SIGNOFF (code 210)
  Message: <nick>

A user on your hotlist has logged off.

BROWSE_RESPONSE (code 212)
  Message: MP3::Napster::Song

During a browse() of another user's shared files, a series of BROWSE_RESPONSE events will be returned, one for each song on the user's share list. The message is converted internally into an MP3::Napster::Song object. This is ordinarily handled internally by the browse() method, but an additional callback can be installed without interference.

BROWSE_RESPONSE_END (code 213)
  Message: none

This event is sent to indicate that list of shared files returned in response to a browse request is done. This is ordinarily handled internally by the browse() method, but an additional callback can be installed without interference.

SERVER_STATS (code 214)
  Message: <users> <files> <gigs>

This event is sent intermittently by the server to give summary statistics. The message consists of the number of users, number of shared files, and total size of shared data in gigabytes, separated by whitespace. For example:

  1021 8772 932

This event is ordinarily ignored.

RESUME_RESPONSE (code 216)
  Message: MP3::Napster::Song

The resume mechanism allows you to complete an interrupted download by searching for users who have songs that match the MD5 sum of the first 300K of the interrupted transfer.

After a RESUME_REQUEST, the server will return a list of all users who have a song that exactly matches the specified MD5 hash fingerprint. Each matching song generates a RESUME_RESPONSE event, similar to a SEARCH_RESPONSE event. The message contains the matching song.

The resume mechanism is not fully implemented in this version of MP3::Napster.

RESUME_RESPONSE_END (code 217)
  Message: none

This event is sent at the end of a series of resume responses.

PUBLIC_MESSAGE (code 403)
  Message: <chan> <nick> <msg>

This event is received when a user sends a public message to one of the channels in which you are enrolled. The message consists of the channel, the user's nickname, and the message, separated by spaces:

    Alternative rastaman What do the colored dots mean?

The fields can be parsed out with this regular expression:

  my ($chan,$nick,$msg) = $message =~ /^(\S+) (\S+) (.*)/;

This event is ignored by default.

INVALID_ENTITY (code 404)
  Message: <error string>

This error message is returned when the client has requested an operation on an invalid user or a channel. This can be used to indicate that the user has gone offline, that the user doesn't exist, or that the channel doesn't exist. Ordinarily this is handled by saving the message and making it available in $nap->error.

JOIN_ACK (code 405)
  Message: <channel>

This event is sent when you have successfully joined a channel. It is ordinarily handled internally by the join_channel() method.

USER_JOINS (code 406)
  Message: MP3::Napster::User

This event is sent when a user joins a channel that you are registered for. The message is an MP3::Napster::User object. To determine which channel generated the event, interrogate the user object's current_channel() method.

USER_DEPARTS (code 407)
  Message:  MP3::Napster::User

The user has departed one of the channels in which you are enrolled. To determine which channel generated the event, interrogate the object's current_channel() method.

CHANNEL_USER_ENTRY (code 408)
  Message: MP3::Napster::User

Soon after joining a channel using join(), the server will return a list of users enrolled in the channel by sending a series of CHANNEL_USER_ENTRY events. The message for each event contains a single MP3::Napster::User object.

This event is ordinarily ignored.

CHANNEL_USER_END (code 409)
  Message: none

This event is sent to indicate the end of a series of CHANNEL_USER_ENTRY events.

CHANNEL_TOPIC (code 410)
  Message: <topic>

This event is sent soon after joining a channel and contains the welcome banner for the channel. Usually ignored.

UPLOAD_REQUEST (code 501)
  Message: <nick> <ip> <port> "<sharename>" <md5> <link>

User <nick> is requesting that you upload to his or her client the shared file named ``sharename'', using the indicated IP address and port to establish an outgoing connection to the remote user's machine. This event is issued when your client is behind a firewall and cannot accept incoming connections. Ordinarily this event is handled internally and you will not want to replace it. For details on the format of the message, see the napster.txt document.

Unlike PASSIVE_UPLOAD_REQUEST, this event requires your client to make an outgoing connection with the indicated client.

Also see PASSIVE_UPLOAD_REQUEST, TRANSFER_STARTED, TRANSFER_IN_PROCESS and TRANSFER_DONE.

LINK_SPEED_RESPONSE (601)
  Message: <nick> <link>

This event is sent in response to a LINK_SPEED_REQUEST message and contains the indicated user's link speed as a small integer. Currently this event is neither triggered by MP3::Napster or handled.

WHOIS_RESPONSE (code 604)
  Message: MP3::Napster::User

This event is returned in response to a whois() method, and contains information about the requested user. Ordinarily it is handled internally by whois().

WHOWAS_RESPONSE (code 605)
  Message: MP3::Napster::User

This event is returned in response to a whois() method when the user is currently offline. It is ordinarily handled internally by whois().

PASSIVE_UPLOAD_REQUEST (code 607)
  Message: <nick> "<sharename>"

User <nick> is notifying your client that it will soon establish an incoming connection to your machine in order to download the shared file named ``filename''. The quotes are part of the message, as in:

  jenz22 "[Antonio Vivaldi] La Notte G minor.mp3"

The ``passive'' part means that your client does not need to establish the connection. It just waits for the remote client's incoming connect.

Ordinarily this event is handled internally. You definitely do not want to replace it.

Also see UPLOAD_REQUEST, TRANSFER_STARTED, TRANSFER_IN_PROCESS and TRANSFER_DONE.

SET_DATA_PORT (code 613)
  Message: <port>

The server sends this event when requesting that the client change its port for incoming connections. The default behavior is to change the port the client is listening on. This may not be what you want if there is a firewall in the way.

CHANNEL_ENTRY (code 618)
  Message: MP3::Napster::Channel

After requesting the channel list using channels() the server will return a series of CHANNEL_ENTRY events, each containing an MP3::Napster::Channel object. You may interrogate the object to get more information about the channel, its users, and topic.

LIST_CHANNELS (code 617)
  Message: none

This indicates that the CHANNEL_ENTRY list is finished.

USER_OFFLINE (code 620)
  Message: <nick>

The user has gone offline. This is returned as an error condition for a variety of user inquiries.

This description may be mistaken, as newer versions of napster.txt describe this as an unknown event code.

MOTD (code 621)
  Message: <line of text>

A series of message-of-the-day messages are returned soon after logging into the system. Each message contains a line of text for display by the client. This event is ordinarily ignored.

PING (code 751)
  Message: <nick>

This event occurs when another user is attempting to ascertain if your client is still alive and connected to the network. The message contains your nickname. The client should respond to the PING event with a PONG message, and in fact the default callback for PING looks like this:

  $self->callback(PING,sub { my $self = shift;
                             $self->send(PONG,$self->nickname) });
USER_LIST_ENTRY (code 825)
  Message: MP3::Napster::User

A series of these events are sent in response to a users() request, each containing an MP3::Napster::User object corresponding to one of the users enrolled in the current channel. This event is ordinarily handled internally by users().

LIST_USERS (code 830)
  Message: none

This is sent at the end of a series of USER_LIST_ENTRY messages to indicate that the list is finished.

TRANSFER_STARTED (code 1024)
  Message: MP3::Napster::Transfer

This event is sent when a download or upload begins. You may examine the MP3::Napster::Transfer object to determine the direction of the transfer and the name of the remote user.

This is actually a pseudo-event generated internally by MP3::Napster, and not part of the Napster protocol itself.

TRANSFER_IN_PROGRESS (code 1025)
  Message: MP3::Napster::Transfer

This event is sent periodically during the course of a download or upload. The precise interval can be adjusted with calls to the Transfer object's interval() method. You may examine the object to determine the status of the transfer, and how many bytes have been transferred.

This is actually a pseudo-event generated internally by MP3::Napster, and not part of the Napster protocol itself.

TRANSFER_DONE (code 1026)
 Message: MP3::Napster::Transfer

This message is sent when a transfer is done. Examine the object to determine whether the transfer was completed normally.

This is actually a pseudo-event generated internally by MP3::Napster, and not part of the Napster protocol itself.

Outgoing Events

This section is a brief summary of the outgoing commands that you can send to the Napster server via the send() method. Most of these commands are easier to issue through API calls, such as $nap->search(). You may need to use these outgoing commands to implement certain features that are not yet part of the API, such as the various Napster administrative functions.

See the napster.txt document for a fuller description of these commands. As with the incoming events, not all of the known commands are documented here, and there are commands issued by the PC client whose significance is not yet understood.

LOGIN (code 2)
  Message: <nick> <password> <port> "<client-version>" <linkspeed>

This requests a login for username <nick> with the specified password, port, client name and version and link type. This message is issued automatically by login().

NEW_LOGIN (code 6)
  Message: <nick> <pass> <port> "<client-version>" <linkspeed> <email-address>

This is an alternative login format that is used immediately after a successful registration request (see below).

REGISTRATION_REQUEST (code 7)
  Message: <nick>

This message requests the registration of a new nickname. It is issued automatically by the register() method.

LOGIN_OPTIONS (code 14)
  Message: NAME:%s ADDRESS:%s CITY:%s STATE:%s PHONE:%s AGE:%s INCOME:%s EDUCATION:%s

This is sent at some point after a successful login or registration in order to upload the indicated information to the Napster server. The description of the message in napster.txt is unclear on when and how the message should be used. It is likely that the current module does not implement it correctly.

I_HAVE (code 100)
  Message: "<sharename>" <md5> <size> <bitrate> <frequency> <time>

This message is sent to register a shared song file with the Napster server. It is normally handled for you by the share() method. See napster.txt for a fuller description.

REMOVE_FILE (code 102)
  Message: "<sharename>"

This message removes the indicated shared song from the list maintained by the server. It is not currently available in the MP3::Napster API.

SEARCH (code 200)
  Message: (see napster.txt)

This message initiates a search for a shared song. The message format is complex, but explained well in napster.txt.

DOWNLOAD_REQ (code 203)
  Message: <nick> "<sharename>"

This message notifies the server of the client's intention to download file ``sharename'' from the indicated user. The server will reply with a DOWNLOAD_ACK. This is normally handled for you by the download() method.

PRIVATE_MESSAGE (code 205)
  Message: <nick> <message>

This message code sends a private message to the indicated user. It is normally handled for you by the private_message() method.

BROWSE_REQUEST (code 211)
  Message: <nick>

This sends a request to the server to browse all the files shared by the indicated user. This is ordinarily issued by the browse() method. The response is returned as a series of BROWSE_RESPOND events.

RESUME_REQUEST (code 215)
  Message: <md5> <size>

This issues a request to search for all songs that match the indicated MD5 hash and file size. This is used to resume previously interrupted transfers. The server replies with a series of RESUME_RESPONSE events.

The resume facility is not yet implemented in MP3::Napster.

DOWNLOADING (code 218)
 Message: none

The client sends this message to the server to indicate that it has begun downloading a song. It does nothing except to bump up the ``download'' count in the user's profile, and is ordinarily handled automatically in the download() method.

DOWNLOAD_COMPLETE (code 219)
  Message: none

This indicates that the client has completed a download, and reduces the download count by one.

UPLOADING (code 220)
  Message: none

This indicates that the client has begun an upload, and is ordinarily issued automatically by the module when it has shared files.

UPLOAD_COMPLETE (code 221)
  Message: none

This message indicates that the client has finished an upload.

JOIN_CHANNEL (code 400)
  Message: <channel>

This is the message that is issued by join() to enroll in a channel. If succesful, the server will return with a JOIN_ACK.

PART_CHANNEL (code 401)
  Message: <channel>

This message is sent when departing a channel, ordinarily issued by the part_channel() method. Oddly, the server doesn't acknowledge this one.

SEND_PUBLIC_MESSAGE (code 402)
  Message: <channel> <message>

This message sends a public message to the indicated channel. It is issued by the public_message() method.

CHANNEL_TOPIC (code 410)
  Message: <channel> <topic>

This message can be sent in order to change the topic assigned to a channel. You probably need special privileges to do this.

PASSIVE_DOWNLOAD_REQ (code 500)
  Message: <nick> "<sharename>"

This message requests that the user <nick> make an outgoing connection to the client's machine and send <sharename>. It's used in the case that the owner of the file is behind a firewall and cannot accept incoming connections. This message is ordinarily issued for you by the download() method.

LINK_SPEED_REQUEST (code 600)
  Message: <nick>

This message requests a user's link speed. The result will be a LINK_SPEED_RESPONSE event.

WHOIS_REQ (code 603)
  Message: <nick>

This requests information about the specified user, ordinarily issued by the whois() method.

LIST_CHANNELS (code 617)
  Message: none

This message is sent to get a list of channels and their topics from the server. The response is a set of CHANNEL_ENTRY events, followed by a LIST_CHANNELS event to end the list (yes, the same event code is used for request and response). This is ordinarily handled for you by the channels() method.

DATA_PORT_ERROR (code 626)
  Message: <nick>

The client sends this message to the server when it has attempted and failed to make an outgoing connection to the indicated user. This is issued when appropriate by MP3::Napster's file transfer routines.

CHANGE_LINK_SPEED (code 700)
  Message: <link>

This message can be issued after login to change the listed link speed for the user. It is sent (perhaps incorrectly?) by the change_registration() method.

CHANGE_PASSWORD (code 701)
   Message: <password>

This message can be issued after login to change the user's password. It is issed by the change_registration() method. Note that napster.txt does not document this code; I found it by accident when trying to change the e-mail address (see below).

CHANGE_EMAIL (code 702)
  Message: <email address>

This message can be issued after login to change the user's e-mail address, or at least so it's documented. In practice, I get a cryptic error message from the server

CHANGE_DATA_PORT (code 703)
  Message: <port>

This message is used to inform the server that the client is now listening on a different port for incoming connections. This message is issued automatically when processing the SET_DATA_PORT event. Ordinarily you will not want to manipulate it directly.

PING (code 751)
  Message: <nick>

This message sends a PING event to the indicated user, ordinarily issued by the ping() method. If the user's client is still online, it will respond with a PONG message.

PONG (code 752)
  Message: <nick>

A client should respond to a PING event with a PONG message. In fact, the default callback for the PING event does exactly that.

LIST_USERS (code 830)
  Message: <channel>

This message requests a list of all the users in the indicated channel. The server replies with a series of USER_LIST_ENTRY events. followed by a final LIST_USERS event (the same code is used both to initiate and terminate a user list). This is ordinarily issued by the users() method.


MORE INFORMATION ON THE NAPSTER PROTOCOL

More information on the Napster protocol can be found in the document ``napster.txt'' that accompanies this module. Other information can be found in the documents and discussion groups available through opennap.sourceforge.net.


AUTHOR

Lincoln Stein <lstein@cshl.org>.


COPYRIGHT

Copyright (c) 2000 Cold Spring Harbor Laboratory. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


SEE ALSO

the MP3::Napster::User manpage, the MP3::Napster::Song manpage, the MP3::Napster::Channel manpage, and the MPEG::Napster::Transfer manpage

 MP3::Napster - Perl interface to the Napster Server