File Coverage

blib/lib/MP3/Album.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package MP3::Album;
2              
3 1     1   43172 use strict;
  1         3  
  1         43  
4 1     1   434 use MP3::Info;
  0            
  0            
5             use MP3::Album::Track;
6             use MP3::Album::Layout::Fetcher;
7             use MP3::Album::Layout;
8             use File::Basename;
9              
10             our $VERSION = '0.14';
11              
12             sub new {
13             my $c = shift;
14             my %a = @_;
15             my $s = { };
16              
17             $s = bless $s, $c;
18            
19             $s->{tracks} = [];
20              
21             if ($a{files}) {
22             $a{files} = [ $a{files} ] if ( ref($a{files}) ne 'ARRAY' );
23             foreach my $f (@{$a{files}}) {
24             my $tr = MP3::Album::Track->new(filename => $f);
25             unless ($tr) { return undef; }
26             push @{$s->{tracks}}, $tr;
27             }
28             }
29              
30             $s->{current_layout} = undef;
31              
32             return $s;
33             }
34              
35             sub rename_files {
36             my $s = shift;
37             my %a = @_;
38              
39             # %t track title;
40             # %a album name
41             # %n track number
42             # %p artist name
43              
44             $a{format} = '%p - %a - %n - %t.mp3' unless $a{format};
45             $a{keep_copy} |= 0;
46            
47             my $layout = $s->layout();
48             my $li = $layout->info();
49              
50             for (my $i = 0; $i < scalar(@{$s->{tracks}}); $i++) {
51             next unless $s->{tracks}->[$i];
52              
53             my $track_number = sprintf("%02d",$i+1);
54              
55             my $fn = $a{format};
56              
57             $fn =~ s/\%p/$li->{tracks}->[$i]->{artist}/g;
58             $fn =~ s/\%a/$li->{title}/g;
59             $fn =~ s/\%n/$track_number/g;
60             $fn =~ s/\%t/$li->{tracks}->[$i]->{title}/g;
61              
62             $fn =~ s/\//_/g;
63              
64             my $dirname = $a{out_dir} ? $a{out_dir} : dirname($s->{tracks}->[$i]->filename());
65              
66             my $r = $s->{tracks}->[$i]->rename(filename=>"$dirname/$fn", keep_copy => $a{keep_copy});
67              
68             return undef unless $r;
69             };
70              
71             return 1;
72             }
73              
74             sub generate_tags {
75             my $s = shift;
76             $s->_init unless $s->{_init_done};
77              
78             my $layout = $s->layout();
79             my $li = $layout->info();
80              
81             for (my $i = 0; $i < scalar(@{$s->{tracks}}); $i++) {
82             next unless $s->{tracks}->[$i];
83              
84             my $track_number = sprintf("%02d",$i+1);
85            
86             my $r = $s->{tracks}->[$i]->set_tag(
87             title => $li->{tracks}->[$i]->{title},
88             artist => $li->{tracks}->[$i]->{artist},
89             album => $li->{title},
90             year => $li->{year},
91             genre => $li->{genre},
92             comment => $li->{comment},
93             track_number => $track_number
94             );
95              
96             return undef unless $r;
97             }
98              
99             return 1;
100              
101             }
102              
103             sub info {
104             my $s = shift;
105             $s->_init unless $s->{_init_done};
106            
107             my %info = (
108             number_oF_tracks => scalar(@{$s->{tracks}}),
109             bitrates => [ $s->_album_bitrate() ],
110             uniform_bitrate => scalar($s->_album_bitrate()) == 1 ? 1 : 0,
111             frequencies => [ $s->_album_frequencies() ],
112             uniform_frequency => scalar($s->_album_frequency()) == 1 ? 1 : 0,
113             cddb_disc_id => $s->{cddb_query}->{discid}
114             );
115             return wantarray ? %info : \%info;
116             }
117              
118             sub frequency_check {
119             my $s = shift;
120             $s->_init unless $s->{_init_done};
121              
122             return scalar($s->_album_frequencies()) == 1 ? 1 : 0;
123             }
124              
125             sub bitrate_check{
126             my $s = shift;
127             $s->_init unless $s->{_init_done};
128              
129             return scalar($s->_album_bitrate()) == 1 ? 1 : 0;
130             }
131              
132             sub tracks {
133             my $s = shift;
134              
135             return @{$s->{tracks}};
136             }
137              
138             sub add {
139             my $s = shift;
140             my %a = @_;
141              
142             $s->_init unless $s->{_init_done};
143              
144             unless ( $a{track} ) {
145             $@ = "missing param track";
146             return undef;
147             }
148              
149             my $tr = MP3::Album::Track->new(filename => $a{track});
150             unless ($tr) { return undef }
151              
152             $a{position} = scalar(@{$s->{tracks}})+1 unless $a{position};
153              
154             if ( $a{position} > scalar(@{$s->{tracks}})+1 ) {
155             $@ = "position must be between start and end of the album";
156             return undef;
157             }
158              
159             my @tracks = @{$s->{tracks}};
160              
161             my @f = splice(@tracks, 0, ($a{position}-1));
162              
163             $s->{tracks} = [@f, $tr, @tracks];
164              
165             delete $s->{_init_done};
166             return 1;
167              
168             };
169              
170             sub layout {
171             my $s = shift;
172             $s->_init unless $s->{_init_done};
173              
174             if (@_) {
175             unless ( $_[0] && (ref $_[0] eq 'MP3::Album::Layout') ) {
176             $@ = "I need a MP3::Album::Layout to set up the album layout";
177             return undef;
178             }
179             $s->{current_layout} = $_[0];
180            
181             } elsif (! $s->{current_layout} ) {
182             my $l = $s->fetch_layout();
183             return undef if (!$l);
184             $s->{current_layout} = $l->[0];
185             }
186              
187             return $s->{current_layout};
188             }
189              
190             sub fetch_layout {
191             my $s = shift;
192             my %a = @_;
193              
194             $s->_init unless $s->{_init_done};
195              
196             $a{method} = 'Tag' unless $a{method};
197              
198             my $layouts = MP3::Album::Layout::Fetcher->fetch(album=>$s, method=>$a{method});
199              
200             return undef unless $layouts;
201              
202             return wantarray ? @$layouts : $layouts;
203             };
204              
205             sub available_fetchers {
206             return MP3::Album::Layout::Fetcher->available_fetchers();
207             }
208              
209             sub _album_frequencies {
210             my $s = shift;
211              
212             my %freqs;
213            
214             foreach my $t (@{$s->{tracks}}) {
215             $freqs{$t->bitrate()}=1 if $t->bitrate();
216             }
217              
218             return keys(%freqs);
219             }
220              
221             sub _album_bitrate {
222             my $s = shift;
223              
224             my %bitrates;
225            
226             foreach my $t (@{$s->{tracks}}) {
227             $bitrates{$t->bitrate()}=1 if $t->bitrate();
228             }
229              
230             return keys(%bitrates);
231             }
232              
233             sub _generate_toc {
234             my $s = shift;
235             my @toc;
236             foreach my $f (@{$s->{tracks}}) {
237             push @toc, $f->{info};
238             }
239             return @toc;
240             }
241              
242             sub _cddb_query_builder {
243             my $s = shift;
244             my %a = @_;
245             die "need a toc to build a query\n" unless $a{toc};
246              
247             my $discid = $s->_disc_id(toc => $a{toc});
248             my $disctime = $s->_disc_time(toc => $a{toc});
249             my $total_tracks = @{$a{toc}};
250             my $frames = $s->_get_frames(toc=> $a{toc});
251              
252             return { discid=> $discid, disctime=>$disctime, disctracks=>$total_tracks, frames=>$frames };
253            
254             }
255              
256             sub _get_frames {
257             my $s = shift;
258             my %a = @_;
259              
260             my @frames;
261             my $t = 0;
262             foreach my $track ( @{$a{toc}} ) {
263             push @frames, $t * 75;
264             $t += ( $track->{MM} * 60 + $track->{SS} );
265             }
266             return \@frames;
267             }
268              
269             sub _disc_time {
270             my $s = shift;
271             my %a = @_;
272             my $total_time = 0;
273              
274             foreach my $track (@{$a{toc}}) {
275             my $track_time = $track->{MM} * 60 + $track->{SS};
276             $total_time += $track_time;
277             }
278              
279             return $total_time;
280             }
281              
282             sub _disc_id {
283             my $s = shift;
284             my %a = @_;
285             my $n = 0;
286             my $total_time = 0;
287              
288             foreach my $track ( @{$a{toc}} ) {
289             my $track_time = $track->{MM} * 60 + $track->{SS};
290              
291             $n += $s->_cddb_sum($total_time);
292             $total_time += $track_time;
293             }
294              
295             return sprintf("%08x", ($n % 0xFF) << 24 | $total_time << 8 | @{$a{toc}});
296             }
297              
298             sub _cddb_sum {
299             my $s = shift;
300             my ($n, $ret) = (shift, 0);
301             for (split //, $n) { $ret += $_ }
302             return $ret;
303             }
304              
305             sub _init {
306             my $s = shift;
307              
308             @{$s->{toc}} = $s->_generate_toc;
309             $s->{cddb_query} = $s->_cddb_query_builder(toc=>$s->{toc});
310              
311             $s->{_init_done} = 1;
312              
313             return 1;
314             }
315              
316             1;