The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Audio::Xmpcr - control an XMPCR device for XM Radio

SYNOPSIS

        use Audio::Xmpcr;

DESCRIPTION

The Audio::Xmpcr module allows you to control an XMPCR device, which is used to tune into the XM satellite radio network. More info can be found at http://www.xmradio.com. The device itself can only be purchased (as of this writing) at PCConnection http://www.pcconnection.com.

The api operates in one of two modes. First, a direct SERIAL mode where the api communicates with the device directly. This is usually not desirable because polling the device for song data is time consuming. Time required to pull an entire channel/song/artist listing is upwards of 10-20 seconds. Also, the device may be shared by several users/programs. Protocol confusion may result if everyone is talking at the same time. Note that the serial mode will write a channel cache file into ~/.xmpcrd-cache, so if the channel list changes, you'll need to delete this file and restart the program. (i.e., since the daemon uses serial mode, you'll need to restart the daemon)

The second mode of operation is NETWORK/DAEMON mode. Here, a daemon runs on the machine connected to the Pcr, and all communication with the daemon is done via sockets. This is preferable for most applications, as the daemon takes care of much of the busy work. In particular, the daemon continuously polls the device, and updates its internal channel listing. The default timing allows 4 channels to be updated each second. Also, every half second, the current channel is updated - since we always want to know when the channel data changes on the current channel. This means that it takes 100/4 or 25 seconds to refresh all channels. When retrieving a channel/song listing, a few channels may be out of date, but will most certainly be correct the next pass through. See the note about the cache file in the SERIAL mode paragraph, above.

The mode is chosen when the device is instantiated - i.e., the constructor is an abstract factory for the two types of connections. Regardless of the mode chosen, the interface supports the same method calls and behaviour with few exceptions. That is, you won't care whether you're talking directly to the device or the daemon - the api will return the same results either way. The following is a list of exceptions to that rule:

list()

Via daemon, this call returns almost immediately; via SERIAL, dramatically slower (i.e., a full channel pull will take between 10-20 secs)

events() and processEvents()

Channel events are not supported in the SERIAL api.

METHOD CALLS

new(KEY => VALUE,...)

Creates a new Xmpcr object. Preferably, use the network mode; use the serial mode if you're unable to run a daemon.

my $radio=new Xmpcr(SERIALPORT => "/dev/ttyUSB0")

or...

my $radio=new Xmpcr(NETHOST => "localhost",NETPORT => 32463,LOCKER => "appname"); (port and locker are optional)

Since many users may use the device when the daemon is running, you have the option of locking the device to prevent channel changes/power off from occuring. When LOCKER is specified, no other networked API user may change the channel or power off if their appname is different. For example, you have a program with the LOCKER 'ripper', which is busily recording show data - you don't want the channel to be changed. Another API user whose appname is 'web-interface' may attempt to change the channel, but the call will be refused. When the locker powers the device off, it will be freed for use by other applications.

It may take a few tens-of-seconds to power on the device, since a channel scan must be performed.

power("on"/"off")

Turns the power to the XmPCR on or off. While off, no commands may be executed (other than to turn the power on).

Returns undef if successful, or an error string if call failed.

mute("on"/"off")

Turns the mute control on or off.

Returns undef if successful, or an error string if call failed.

setchannel(integer)

Sets the receiver channel.

Returns undef if successful, or an error string if call failed.

list() (pull entire channel list)
list(integer) (pull single channel list)

Loads channel data. The "single channel" mode returns a reference to a single hash; the "entire list mode" returns an array of hashes. In serial mode (both entire and single list), the data is pulled directly from the device; the full channel listing takes some time. In network mode, a single channel is also pulled directly from the device (since it's fairly quick), but a full channel listing is pulled from a cache. This cache is continually refreshed in the background by the daemon, about every 20 seconds. Therefore, when the network/entire list is pulled, there's a chance that a few of the song titles will be incorrect, but they will be corrected shortly thereafter. (The currently selected channel is refreshed every .5 second, so it will always be accurate). A channel entry has the keys:

NUM

Channel number

NAME

Name of channel

CAT

Category of channel

SONG

Title of song

ARTIST

Name of artist

returns an empty hash/array if the operation fails.

status()

Returns status data. Returns a hash with the following keys:

POWER

on/off

ANTENNA

0-100 (percent)

NUM

integer (channel num)

NAME

string (channel name)

CAT

string (channel category)

SONG

string (currently playing song)

ARTIST

string (currently playing artist)

RADIOID

8-character string

Hash may have undefined/null values if operation failed - but POWER will always be defined.

events("on"/"off")

Turns event delivery on or off. Whenever a song changes, the API will automatically track channels that change songs, and deliver these changes to you. (see the processEvents() call)

This call is only supported in network mode, and always returns success.

processEvents()

If event delivery is enabled, you may use this call to see which channels have changed songs. It returns an array of hashes, each containing data about any channels that have changed. See the list() method for a hash key description.

Because the daemon broadcasts event changes to all interested parties, it is important that you call processEvents() periodically - perhaps every second - to avoid buffer overrun and data loss. (The alternative is to provide a separate thread to check the daemon, but not every environment is ready to run threads yet). You may also use the eventFd() call for use in select() statements (see eventFd()).

This call is only supported in network mode. An empty list will be returned if event deliver (via events()) is disabled.

eventFd()

Returns a single file descriptor (*not* a file handle) for use in select() calls. Useful when you need to monitor your own file handles for input/output, and also need to check for song events. When select indicates that the descriptor is ready for I/O, call processEvents to determine what was sent. Please do not try to send or receive data using the descriptor; let the API do that.

forcelock()

If the PCR is locked by a program that has exited and was unable to turn off the radio, the daemon may remain locked, and no other programs will be able to use the device. This call removes the lock, allowing the radio to be turned off via the 'power' call.

AUTHOR AND COPYRIGHT

This code is modeled after a Perl module written by Chris Carlson (c@rlson.net). Only the low-level protocol communication was derived from his work (which was further derived from another author's Visual Basic project).

Copyright (c) 2003 Paul Bournival. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License, distributed with Perl.

SEE ALSO

The XMPCR module, available from http://xmpcr.sf.net

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 85:

=back doesn't take any parameters, but you said =back 1

Around line 216:

=back doesn't take any parameters, but you said =back 1