File Coverage

blib/lib/Net/FreeDB.pm
Criterion Covered Total %
statement 33 160 20.6
branch 0 64 0.0
condition 0 12 0.0
subroutine 11 41 26.8
pod 6 8 75.0
total 50 285 17.5


line stmt bran cond sub pod time code
1             package Net::FreeDB;
2              
3 1     1   18064 use 5.006;
  1         5  
  1         50  
4 1     1   6 use strict;
  1         3  
  1         48  
5 1     1   6 use warnings;
  1         2  
  1         55  
6 1     1   731 use IO::Socket;
  1         23109  
  1         4  
7 1     1   955 use Net::Cmd;
  1         4031  
  1         123  
8 1     1   497 use CDDB::File;
  1         3740  
  1         32  
9 1     1   6 use Carp;
  1         1  
  1         51  
10 1     1   4 use Data::Dumper;
  1         1  
  1         35  
11 1     1   766 use File::Temp;
  1         9064  
  1         85  
12              
13             require Exporter;
14             require DynaLoader;
15 1     1   454 use AutoLoader;
  1         1362  
  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.09';
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     my $constname;
41 0           our $AUTOLOAD;
42 0           ($constname = $AUTOLOAD) =~ s/.*:://;
43 0 0         croak "& not defined" if $constname eq 'constant';
44 0 0         my $val = constant($constname, @_ ? $_[0] : 0);
45 0 0         if ($! != 0) {
46 0 0 0       if ($! =~ /Invalid/ || $!{EINVAL}) {
47 0           $AutoLoader::AUTOLOAD = $AUTOLOAD;
48 0           goto &AutoLoader::AUTOLOAD;
49             }
50             else {
51 0           croak "Your vendor has not defined Net::FreeDB macro $constname";
52             }
53             }
54             {
55 1     1   209 no strict 'refs';
  1         1  
  1         2042  
  0            
56             # Fixed between 5.005_53 and 5.005_61
57 0 0         if ($] >= 5.00561) {
58 0     0     *$AUTOLOAD = sub () { $val };
  0            
59             }
60             else {
61 0     0     *$AUTOLOAD = sub { $val };
  0            
62             }
63             }
64 0           goto &$AUTOLOAD;
65             }
66              
67             bootstrap Net::FreeDB $VERSION;
68              
69             # Preloaded methods go here.
70             sub new {
71 0     0 1   my $class = shift;
72 0           my $self = {};
73 0           $self = {@_};
74 0           bless($self, $class);
75              
76 0 0         $self->{HOST} = 'freedb.freedb.org' unless defined($self->{HOST});
77 0 0         $self->{PORT} = '8880' unless defined($self->{PORT});
78              
79 0 0         if (!defined($self->{USER})) {
80 0 0         $self->{USER} = defined($ENV{USER}) ? $ENV{USER} : 'unknown';
81             }
82              
83 0 0         if (!defined($self->{HOSTNAME})) {
84 0 0         $self->{HOSTNAME} = defined($ENV{HOSTNAME}) ? $ENV{HOSTNAME} : 'unknown';
85             }
86              
87 0 0         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 0 0         unless defined $obj;
96              
97 0           $obj->autoflush(1);
98 0 0         $obj->debug(exists $self->{DEBUG} ? $self->{DEBUG} : undef);
99              
100 0 0         unless ($obj->response() == CMD_OK) {
101 0           $obj->close;
102 0           return undef;
103             }
104              
105             $obj->command(
106 0           "cddb hello",
107             $self->{USER},
108             $self->{HOSTNAME},
109             ref($self),
110             $VERSION
111             );
112              
113 0 0         unless ($obj->response() == CMD_OK) {
114 0           $obj->close;
115 0           return undef;
116             }
117              
118 0           $obj;
119             }
120              
121             sub read {
122 0     0 1   my $self = shift;
123 0           my ($cat, $id);
124              
125 0 0         if (scalar(@_) == 2) {
126 0           ($cat, $id) = @_;
127             } else {
128 0 0         if ((scalar(@_) % 2) == 0) {
129 0 0 0       if ($_[0] =~ /^CATEGORY$/i || $_[0] =~ /^ID$/i) {
130 0           my %input = @_;
131 0           ($cat, $id) = ($input{CATEGORY}, $input{ID});
132             } else {
133 0           print "Error: Unknown input!\n";
134 0           return undef;
135             }
136             } else {
137 0           print "Error: Unknown input!\n";
138 0           return undef;
139             }
140             }
141              
142             # First, fetch the data, before creating any temporary files
143 0 0         my $data = $self->_READ($cat, $id)? $self->_read(): undef;
144 0 0         return undef unless defined $data;
145            
146             # Create a file for CDDB::File to use...
147 0           my $fh = new File::Temp;
148 0           print $fh join '', @$data;
149 0           seek $fh, 0, 0;
150              
151             # ...and use it.
152 0           my $cddb_file = new CDDB::File($fh->filename());
153 0           return $cddb_file;
154             }
155              
156             sub query {
157 0     0 1   my $self = shift;
158 0 0         $self->_QUERY(@_) ? $self->_query : undef;
159             }
160              
161             sub sites {
162 0     0 1   my $self = shift;
163 0 0         $self->_SITES ? $self->_sites : undef;
164             }
165              
166             sub getdiscid {
167 0     0 1   my $self = shift;
168 0           my ($driveNo, $id);
169 0 0         if (ref($self) ne 'Net::FreeDB') {
170 0           $driveNo = $self;
171             } else {
172 0           $driveNo = shift;
173             }
174 0           $id = discid($driveNo);
175 0 0 0       if ($id eq "UNDEF" || $id eq '') {
176 0           $ERROR = "Drive Error: no disc found\n";
177 0           return undef;
178             }
179 0           return $id;
180             }
181              
182             sub getdiscdata {
183 0     0 1   my $self = shift;
184 0           my ($driveNo, $data);
185 0 0         if (ref($self) ne 'Net::FreeDB') {
186 0           $driveNo = $self;
187             } else {
188 0           $driveNo = shift;
189             }
190 0           $data = discinfo($driveNo);
191 0 0         if (!$data) {
192 0           $ERROR = "Drive Error: no disc found\n";
193 0           return undef;
194             }
195 0           return $data;
196             }
197              
198             sub lscat {
199 0     0 0   my $self = shift;
200 0           $self->_LSCAT();
201             }
202             sub quit {
203 0     0 0   my $self = shift;
204 0           $self->_QUIT();
205             }
206              
207             sub DESTROY {
208 0     0     my $self = shift;
209 0           $self = {};
210             }
211              
212             sub _read {
213 0     0     my $self = shift;
214 0 0         my $data = $self->read_until_dot or
215             return undef;
216 0           return $data;
217             }
218              
219             sub _query {
220 0     0     my $self = shift;
221 0           my $data = $self->message();
222 0           my $code = $self->code();
223 0           my @returns;
224 0 0 0       if ($code == 210 || $code == 211) {
225              
226              
227 0 0         my $data = $self->read_until_dot
228             or return undef;
229 0           foreach my $i (@{$data}) {
  0            
230 0 0         next if $i =~ /^\.$/;
231 0           $i =~
232             /([^\s]+)\s([^\s]+)\s([^\/|\:|\-]+)\s[\/|\|:|\-]\s?(.*)\s?/;
233 0           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 0           $data =~ /([^\s]+)\s([^\s]+)\s([^\/|\:|\-]+)\s[\/|\:|\-]\s?(.*)\s?/;
238 0           push @returns, {GENRE=>$1,DISCID=>$2,ARTIST=>$3,ALBUM=>$4};
239             }
240 0           return @returns;
241             }
242              
243             sub _sites {
244 0     0     my $self = shift;
245 0 0         my $data = $self->read_until_dot
246             or return undef;
247 0           my @sites;
248 0           foreach (@$data) {
249 0           s/([^\s]+)\s([^\s]+).*/$1 $2/;
250 0           push(@sites, $_);
251             }
252 0           return \@sites;
253             }
254              
255 0     0     sub _READ { shift->command('CDDB READ',@_)->response == CMD_OK }
256 0     0     sub _SITES { shift->command('SITES',@_)->response == CMD_OK }
257 0     0     sub _LSCAT { shift->command('CDDB LSCAT')->response == CMD_OK }
258 0     0     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__