File Coverage

blib/lib/Audio/Xmpcr.pm
Criterion Covered Total %
statement 14 17 82.3
branch 3 6 50.0
condition n/a
subroutine 4 4 100.0
pod 1 1 100.0
total 22 28 78.5


line stmt bran cond sub pod time code
1             package Audio::Xmpcr;
2              
3             $VERSION="1.02";
4              
5 1     1   17767 use strict;
  1         2  
  1         170  
6 1     1   575 use Audio::Xmpcr::Serial;
  1         3  
  1         38  
7 1     1   664 use Audio::Xmpcr::Network;
  1         3  
  1         212  
8              
9             sub new {
10 1     1 1 573 my($class,%args)=@_;
11 1 50       10 if ($args{SERIALPORT}) {
    50          
    50          
12 0         0 return new Audio::Xmpcr::Serial($args{SERIALPORT});
13             } elsif ($args{NETHOST}) {
14 0         0 return new Audio::Xmpcr::Network($args{NETHOST},$args{NETPORT},
15             $args{LOCKER});
16             } elsif ($args{LOADTEST}) {
17             # just return a blessed hash, for loading/testing purposes
18 1         3 my $ref={};
19 1         3 bless $ref, $class;
20 1         4 return $ref;
21             } else {
22 0           die "Xmpcr: unknown API mode - must use either NET/SERIAL method.\n";
23             }
24             }
25              
26             =pod
27              
28             =head1 NAME
29              
30             Audio::Xmpcr - control an XMPCR device for XM Radio
31              
32             =head1 SYNOPSIS
33              
34             use Audio::Xmpcr;
35              
36             =head1 DESCRIPTION
37              
38             The Audio::Xmpcr module allows you to control an XMPCR device,
39             which is used to tune into the XM satellite radio network.
40             More info can be found at http://www.xmradio.com. The device
41             itself can only be purchased (as of this writing) at PCConnection
42             http://www.pcconnection.com.
43              
44             The api operates in one of two modes. First, a direct SERIAL
45             mode where the api communicates with the device directly. This is usually
46             not desirable because polling the device for song data is time consuming.
47             Time required to pull an entire channel/song/artist listing is upwards
48             of 10-20 seconds. Also, the device may be shared by several users/programs.
49             Protocol confusion may result if everyone is talking at the same time.
50             Note that the serial mode will write a channel cache file into
51             ~/.xmpcrd-cache, so if the channel list changes, you'll need to delete
52             this file and restart the program. (i.e., since the daemon uses serial
53             mode, you'll need to restart the daemon)
54              
55             The second mode of operation is NETWORK/DAEMON mode. Here, a daemon
56             runs on the machine connected to the Pcr, and all communication with the
57             daemon is done via sockets. This is preferable for most applications, as
58             the daemon takes care of much of the busy work. In particular, the
59             daemon continuously polls the device, and updates its internal channel
60             listing. The default timing allows 4 channels to be updated each second.
61             Also, every half second, the current channel is updated - since we always
62             want to know when the channel data changes on the current channel. This
63             means that it takes 100/4 or 25 seconds to refresh all channels. When
64             retrieving a channel/song listing, a few channels may be out of date,
65             but will most certainly be correct the next pass through. See the note
66             about the cache file in the SERIAL mode paragraph, above.
67              
68             The mode is chosen when the device is instantiated - i.e., the constructor
69             is an abstract factory for the two types of connections. Regardless of the
70             mode chosen, the interface supports the same method calls and behaviour
71             with few exceptions. That is, you won't care whether you're talking
72             directly to the device or the daemon - the api will return the same
73             results either way. The following is a list of exceptions to that rule:
74              
75             =over 1
76              
77             =item list()
78              
79             Via daemon, this call returns almost immediately; via SERIAL, dramatically slower (i.e., a full channel pull will take between 10-20 secs)
80              
81             =item events() and processEvents()
82              
83             Channel events are not supported in the SERIAL api.
84              
85             =back 1
86              
87             =head1 METHOD CALLS
88              
89             =over 4
90              
91             =item new(KEY => VALUE,...)
92              
93             Creates a new Xmpcr object. Preferably, use the network mode;
94             use the serial mode if you're unable to run a daemon.
95              
96             my $radio=new Xmpcr(SERIALPORT => "/dev/ttyUSB0")
97              
98             or...
99              
100             my $radio=new Xmpcr(NETHOST => "localhost",NETPORT => 32463,LOCKER => "appname");
101             (port and locker are optional)
102              
103             Since many users may use the device when the daemon is running, you have
104             the option of locking the device to prevent channel changes/power off
105             from occuring. When LOCKER is specified, no other networked API user
106             may change the channel or power off if their appname is different. For
107             example, you have a program with the LOCKER 'ripper', which is busily
108             recording show data - you don't want the channel to be changed. Another
109             API user whose appname is 'web-interface' may attempt to change the
110             channel, but the call will be refused. When the locker powers the
111             device off, it will be freed for use by other applications.
112              
113             It may take a few tens-of-seconds to power on the device, since a
114             channel scan must be performed.
115              
116             =item power("on"/"off")
117              
118             Turns the power to the XmPCR on or off. While off, no commands may
119             be executed (other than to turn the power on).
120              
121             Returns undef if successful, or an error string if call failed.
122              
123             =item mute("on"/"off")
124              
125             Turns the mute control on or off.
126              
127             Returns undef if successful, or an error string if call failed.
128              
129             =item setchannel(integer)
130              
131             Sets the receiver channel.
132              
133             Returns undef if successful, or an error string if call failed.
134              
135             =item list() (pull entire channel list)
136              
137             =item list(integer) (pull single channel list)
138              
139             Loads channel data. The "single channel" mode returns a reference
140             to a single hash; the "entire list mode" returns an array of hashes.
141             In serial mode (both entire and single list), the data is pulled
142             directly from the device; the full channel listing takes some time.
143             In network mode, a single channel is also pulled directly from the
144             device (since it's fairly quick), but a full channel listing is
145             pulled from a cache. This cache is continually refreshed in the
146             background by the daemon, about every 20 seconds. Therefore, when
147             the network/entire list is pulled, there's a chance that a few of the
148             song titles will be incorrect, but they will be corrected shortly
149             thereafter. (The currently selected channel is refreshed every
150             .5 second, so it will always be accurate). A channel entry has the keys:
151              
152             =over 1
153              
154             =item NUM
155              
156             Channel number
157              
158             =item NAME
159              
160             Name of channel
161              
162             =item CAT
163              
164             Category of channel
165              
166             =item SONG
167              
168             Title of song
169              
170             =item ARTIST
171              
172             Name of artist
173              
174             =back
175              
176             returns an empty hash/array if the operation fails.
177              
178             =item status()
179              
180             Returns status data. Returns a hash with the following keys:
181              
182             =over 1
183              
184             =item POWER
185              
186             on/off
187              
188             =item ANTENNA
189              
190             0-100 (percent)
191              
192             =item NUM
193              
194             integer (channel num)
195              
196             =item NAME
197              
198             string (channel name)
199              
200             =item CAT
201              
202             string (channel category)
203              
204             =item SONG
205              
206             string (currently playing song)
207              
208             =item ARTIST
209              
210             string (currently playing artist)
211              
212             =item RADIOID
213              
214             8-character string
215              
216             =back 1
217              
218             Hash may have undefined/null values if operation failed - but POWER will
219             always be defined.
220              
221             =item events("on"/"off")
222              
223             Turns event delivery on or off. Whenever a song changes, the API will
224             automatically track channels that change songs, and deliver these
225             changes to you. (see the processEvents() call)
226              
227             This call is only supported in network mode, and always returns success.
228              
229             =item processEvents()
230              
231             If event delivery is enabled, you may use this call to see which
232             channels have changed songs. It returns an array of hashes, each containing
233             data about any channels that have changed. See the list() method for
234             a hash key description.
235              
236             Because the daemon broadcasts event changes to all interested parties,
237             it is important that you call processEvents() periodically - perhaps
238             every second - to avoid buffer overrun and data loss. (The alternative
239             is to provide a separate thread to check the daemon, but not every environment
240             is ready to run threads yet). You may also use the eventFd() call for
241             use in select() statements (see eventFd()).
242              
243             This call is only supported in network mode. An empty list will be
244             returned if event deliver (via events()) is disabled.
245              
246             =item eventFd()
247              
248             Returns a single file descriptor (*not* a file handle) for use in
249             select() calls. Useful when you need to monitor your own file handles
250             for input/output, and also need to check for song events. When select
251             indicates that the descriptor is ready for I/O, call processEvents to
252             determine what was sent. Please do not try to send or receive data using
253             the descriptor; let the API do that.
254              
255             =item forcelock()
256              
257             If the PCR is locked by a program that has exited and was unable to
258             turn off the radio, the daemon may remain locked, and no other programs
259             will be able to use the device. This call removes the lock, allowing
260             the radio to be turned off via the 'power' call.
261              
262             =back
263              
264             =head1 AUTHOR AND COPYRIGHT
265              
266             This code is modeled after a Perl module written by Chris Carlson
267             (c@rlson.net). Only the low-level protocol communication was derived
268             from his work (which was further derived from another author's Visual
269             Basic project).
270              
271             Copyright (c) 2003 Paul Bournival. All rights reserved. This program is
272             free software; you can redistribute it and/or modify it under the terms
273             of the Artistic License, distributed with Perl.
274              
275             =head1 SEE ALSO
276              
277             The XMPCR module, available from http://xmpcr.sf.net
278              
279              
280             =cut
281              
282             1;