File Coverage

blib/lib/Net/FreeDB.pm
Criterion Covered Total %
statement 113 160 70.6
branch 26 64 40.6
condition 3 12 25.0
subroutine 26 41 63.4
pod 6 8 75.0
total 174 285 61.0


line stmt bran cond sub pod time code
1             package Net::FreeDB;
2              
3 1     1   23088 use 5.006;
  1         4  
  1         41  
4 1     1   7 use strict;
  1         3  
  1         37  
5 1     1   6 use warnings;
  1         1  
  1         29  
6 1     1   914 use IO::Socket;
  1         25599  
  1         5  
7 1     1   1291 use Net::Cmd;
  1         4986  
  1         96  
8 1     1   895 use CDDB::File;
  1         4223  
  1         34  
9 1     1   8 use Carp;
  1         2  
  1         56  
10 1     1   6 use Data::Dumper;
  1         2  
  1         44  
11 1     1   1218 use File::Temp;
  1         9906  
  1         144  
12              
13             require Exporter;
14             require DynaLoader;
15 1     1   837 use AutoLoader;
  1         1569  
  1         6  
16              
17             our @ISA = qw(Exporter DynaLoader Net::Cmd IO::Socket::INET);
18              
19             # Items to export into callers namespace by default. Note: do not export
20             # names by default without a very good reason. Use EXPORT_OK instead.
21             # Do not simply export all your public functions/methods/constants.
22              
23             # This allows declaration use Net::FreeDB ':all';
24             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
25             # will save memory.
26             our %EXPORT_TAGS = ( 'all' => [ qw() ] );
27              
28             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
29              
30             our @EXPORT = qw();
31              
32             our $VERSION = '0.08';
33              
34             our $ERROR;
35             sub AUTOLOAD {
36             # This AUTOLOAD is used to 'autoload' constants from the constant()
37             # XS function. If a constant is not found then control is passed
38             # to the AUTOLOAD in AutoLoader.
39              
40 0     0   0 my $constname;
41 0         0 our $AUTOLOAD;
42 0         0 ($constname = $AUTOLOAD) =~ s/.*:://;
43 0 0       0 croak "& not defined" if $constname eq 'constant';
44 0 0       0 my $val = constant($constname, @_ ? $_[0] : 0);
45 0 0       0 if ($! != 0) {
46 0 0 0     0 if ($! =~ /Invalid/ || $!{EINVAL}) {
47 0         0 $AutoLoader::AUTOLOAD = $AUTOLOAD;
48 0         0 goto &AutoLoader::AUTOLOAD;
49             }
50             else {
51 0         0 croak "Your vendor has not defined Net::FreeDB macro $constname";
52             }
53             }
54             {
55 1     1   269 no strict 'refs';
  1         2  
  1         3488  
  0         0  
56             # Fixed between 5.005_53 and 5.005_61
57 0 0       0 if ($] >= 5.00561) {
58 0     0   0 *$AUTOLOAD = sub () { $val };
  0         0  
59             }
60             else {
61 0     0   0 *$AUTOLOAD = sub { $val };
  0         0  
62             }
63             }
64 0         0 goto &$AUTOLOAD;
65             }
66              
67             bootstrap Net::FreeDB $VERSION;
68              
69             # Preloaded methods go here.
70             sub new {
71 1     1 1 124 my $class = shift;
72 1         3 my $self = {};
73 1         3 $self = {@_};
74 1         3 bless($self, $class);
75              
76 1 50       23 $self->{HOST} = 'freedb.freedb.org' unless defined($self->{HOST});
77 1 50       4 $self->{PORT} = '8880' unless defined($self->{PORT});
78              
79 1 50       5 if (!defined($self->{USER})) {
80 0 0       0 $self->{USER} = defined($ENV{USER}) ? $ENV{USER} : 'unknown';
81             }
82              
83 1 50       6 if (!defined($self->{HOSTNAME})) {
84 1 50       6 $self->{HOSTNAME} = defined($ENV{HOSTNAME}) ? $ENV{HOSTNAME} : 'unknown';
85             }
86              
87 1 50       28 my $obj = $self->SUPER::new(PeerAddr => $self->{HOST},
88             PeerPort => $self->{PORT},
89             Proto => 'tcp',
90             Timeout =>
91             defined($self->{TIMEOUT}) ? $self->{TIMEOUT} : 120
92             );
93              
94             return undef
95 1 50       71087 unless defined $obj;
96              
97 1         13 $obj->autoflush(1);
98 1 50       81 $obj->debug(exists $self->{DEBUG} ? $self->{DEBUG} : undef);
99              
100 1 50       78 unless ($obj->response() == CMD_OK) {
101 0         0 $obj->close;
102 0         0 return undef;
103             }
104              
105             $obj->command(
106 1         39249 "cddb hello",
107             $self->{USER},
108             $self->{HOSTNAME},
109             ref($self),
110             $VERSION
111             );
112              
113 1 50       253 unless ($obj->response() == CMD_OK) {
114 0         0 $obj->close;
115 0         0 return undef;
116             }
117              
118 1         32956 $obj;
119             }
120              
121             sub read {
122 1     1 1 5 my $self = shift;
123 1         2 my ($cat, $id);
124              
125 1 50       10 if (scalar(@_) == 2) {
126 1         6 ($cat, $id) = @_;
127             } else {
128 0 0       0 if ((scalar(@_) % 2) == 0) {
129 0 0 0     0 if ($_[0] =~ /^CATEGORY$/i || $_[0] =~ /^ID$/i) {
130 0         0 my %input = @_;
131 0         0 ($cat, $id) = ($input{CATEGORY}, $input{ID});
132             } else {
133 0         0 print "Error: Unknown input!\n";
134 0         0 return undef;
135             }
136             } else {
137 0         0 print "Error: Unknown input!\n";
138 0         0 return undef;
139             }
140             }
141              
142             # First, fetch the data, before creating any temporary files
143 1 50       6 my $data = $self->_READ($cat, $id)? $self->_read(): undef;
144 1 50       8 return undef unless defined $data;
145            
146             # Create a file for CDDB::File to use...
147 1         15 my $fh = new File::Temp;
148 1         1059 print $fh join '', @$data;
149 1         115 seek $fh, 0, 0;
150              
151             # ...and use it.
152 1         9 my $cddb_file = new CDDB::File($fh->filename());
153 1         287 return $cddb_file;
154             }
155              
156             sub query {
157 2     2 1 643 my $self = shift;
158 2 50       12 $self->_QUERY(@_) ? $self->_query : undef;
159             }
160              
161             sub sites {
162 1     1 1 3 my $self = shift;
163 1 50       5 $self->_SITES ? $self->_sites : undef;
164             }
165              
166             sub getdiscid {
167 2     2 1 34122 my $self = shift;
168 2         5 my ($driveNo, $id);
169 2 100       9 if (ref($self) ne 'Net::FreeDB') {
170 1         3 $driveNo = $self;
171             } else {
172 1         4 $driveNo = shift;
173             }
174 2         64 $id = discid($driveNo);
175 2 50 33     18 if ($id eq "UNDEF" || $id eq '') {
176 2         5 $ERROR = "Drive Error: no disc found\n";
177 2         7 return undef;
178             }
179 0         0 return $id;
180             }
181              
182             sub getdiscdata {
183 1     1 1 127 my $self = shift;
184 1         3 my ($driveNo, $data);
185 1 50       5 if (ref($self) ne 'Net::FreeDB') {
186 1         3 $driveNo = $self;
187             } else {
188 0         0 $driveNo = shift;
189             }
190 1         25 $data = discinfo($driveNo);
191 1 50       4 if (!$data) {
192 0         0 $ERROR = "Drive Error: no disc found\n";
193 0         0 return undef;
194             }
195 1         3 return $data;
196             }
197              
198             sub lscat {
199 1     1 0 2 my $self = shift;
200 1         5 $self->_LSCAT();
201             }
202             sub quit {
203 0     0 0 0 my $self = shift;
204 0         0 $self->_QUIT();
205             }
206              
207             sub DESTROY {
208 1     1   4 my $self = shift;
209 1         18 $self = {};
210             }
211              
212             sub _read {
213 1     1   35398 my $self = shift;
214 1 50       21 my $data = $self->read_until_dot or
215             return undef;
216 1         69532 return $data;
217             }
218              
219             sub _query {
220 2     2   118135 my $self = shift;
221 2         41 my $data = $self->message();
222 2         54 my $code = $self->code();
223 2         31 my @returns;
224 2 100 66     30 if ($code == 210 || $code == 211) {
225              
226              
227 1 50       8 my $data = $self->read_until_dot
228             or return undef;
229 1         837 foreach my $i (@{$data}) {
  1         4  
230 10 50       25 next if $i =~ /^\.$/;
231 10         38 $i =~
232             /([^\s]+)\s([^\s]+)\s([^\/|\:|\-]+)\s[\/|\|:|\-]\s?(.*)\s?/;
233 10         156 push @returns, {GENRE =>$1,DISCID =>$2,ARTIST=>$3,ALBUM=>$4};
234             }
235             } else {
236             #we got a single; parse it, hash it and return it
237 1         12 $data =~ /([^\s]+)\s([^\s]+)\s([^\/|\:|\-]+)\s[\/|\:|\-]\s?(.*)\s?/;
238 1         17 push @returns, {GENRE=>$1,DISCID=>$2,ARTIST=>$3,ALBUM=>$4};
239             }
240 2         35 return @returns;
241             }
242              
243             sub _sites {
244 1     1   32886 my $self = shift;
245 1 50       11 my $data = $self->read_until_dot
246             or return undef;
247 1         81 my @sites;
248 1         6 foreach (@$data) {
249 1         16 s/([^\s]+)\s([^\s]+).*/$1 $2/;
250 1         5 push(@sites, $_);
251             }
252 1         12 return \@sites;
253             }
254              
255 1     1   11 sub _READ { shift->command('CDDB READ',@_)->response == CMD_OK }
256 1     1   7 sub _SITES { shift->command('SITES',@_)->response == CMD_OK }
257 1     1   17 sub _LSCAT { shift->command('CDDB LSCAT')->response == CMD_OK }
258 2     2   16 sub _QUERY { shift->command('CDDB QUERY',@_)->response == CMD_OK }
259 0     0     sub _QUIT { shift->command('QUIT')->response == CMD_OK }
260              
261 0     0     sub _WRITE { shift->command('CDDB WRITE',@_)->response == CMD_OK }
262 0     0     sub _WHOM { shift->command('CDDB WHOM')->response == CMD_OK }
263 0     0     sub _UPDATE { shift->command('CDDB UPDATE')->response == CMD_OK }
264 0     0     sub _VER { shift->command('CDDB VER')->response == CMD_OK }
265 0     0     sub _STAT { shift->command('CDDB STAT')->response == CMD_OK }
266 0     0     sub _PROTO { shift->command('CDDB PROTO')->response == CMD_OK }
267 0     0     sub _MOTD { shift->command('CDDB MOTD')->response == CMD_OK }
268 0     0     sub _LOG { shift->command('CDDB LOG',@_)->response == CMD_OK }
269 0     0     sub _HELP { shift->command('CDDB HELP')->response == CMD_OK }
270 0     0     sub _DISCID { shift->command('DISCID',@_)->response == CMD_OK }
271              
272              
273             1;
274             __END__