File Coverage

blib/lib/MP3/Tag/Utils.pm
Criterion Covered Total %
statement 12 168 7.1
branch 0 50 0.0
condition 0 30 0.0
subroutine 4 11 36.3
pod 7 7 100.0
total 23 266 8.6


line stmt bran cond sub pod time code
1             package MP3::Tag::Utils;
2              
3 1     1   31418 use warnings;
  1         3  
  1         41  
4 1     1   7 use strict;
  1         2  
  1         75  
5 1     1   1494 use MP3::Tag;
  1         82120  
  1         57  
6 1     1   1111 use Text::NeatTemplate;
  1         4693  
  1         2215  
7              
8             =head1 NAME
9              
10             MP3::Tag::Utils - Assorted utilities for manipulating MP3 files via MP3::Tag.
11              
12             =head1 VERSION
13              
14             Version 0.0.3
15              
16             =cut
17              
18             our $VERSION = '0.0.3';
19              
20              
21             =head1 SYNOPSIS
22              
23             use MP3::Tag::Utils;
24              
25             my $foo = MP3::Tag::Utils->new();
26             ...
27              
28             =head1 METHODS
29              
30             =head2 new
31              
32             =cut
33              
34             sub new{
35 0     0 1   my %args;
36 0 0         if (defined($_[1])) {
37 0           %args=%{$_[1]};
  0            
38             }
39 0           my $method='new';
40            
41            
42 0           my $self={
43             perror=>undef,
44             error=>undef,
45             errorString=>'',
46             module=>'MP3-Tag-Utils',
47             };
48 0           bless $self;
49            
50 0           return $self;
51             }
52              
53             =head2 change
54              
55             Change the tags on a MP3 file.
56              
57             =head3 args hash
58              
59             =head4 file
60              
61             The file to operate on.
62              
63             =head4 album
64              
65             If this is defined, the tag is set to it.
66              
67             =head4 artist
68              
69             If this is defined, the tag is set to it.
70              
71             =head4 comment
72              
73             If this is defined, the tag is set to it.
74              
75             =head4 genre
76              
77             If this is defined, the tag is set to it.
78              
79             =head4 title
80              
81             If this is defined, the tag is set to it.
82              
83             =head4 track
84              
85             If this is defined, the tag is set to it.
86              
87             =head4 year
88              
89             If this is defined, the tag is set to it.
90              
91             $foo->change(\%args);
92             if($foo->error){
93             warn('Error '.$foo->error.': '.$foo->errorString);
94             }
95              
96             =cut
97              
98             sub change{
99 0     0 1   my $self=$_[0];
100 0           my %args;
101 0 0         if (defined($_[1])) {
102 0           %args=%{$_[1]};
  0            
103             }
104 0           my $method='rename';
105              
106             #blanks any previous errors
107 0 0         if (!$self->errorblank) {
108 0           warn($self->{module}.' '.$method.': Unable to blank previous error');
109 0           return undef;
110             }
111            
112             #makes sure some files are specified.
113 0 0         if (!defined($args{file})) {
114 0           $self->{error}=1;
115 0           $self->{errorString}='No file specified';
116 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
117 0           return undef;
118             }
119              
120            
121             #make sure something to change is specified
122 0 0 0       if (
      0        
      0        
      0        
      0        
      0        
123             (!defined( $args{album} )) &&
124             (!defined( $args{artist} )) &&
125             (!defined( $args{comment} )) &&
126             (!defined( $args{genre} )) &&
127             (!defined( $args{title} )) &&
128             (!defined( $args{track} )) &&
129             (!defined( $args{year} ))
130             ) {
131 0           $self->{error}=3;
132 0           $self->{errorString}='Nothing specified to change';
133 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
134 0           return undef;
135             }
136              
137             #makes sure it appears to be a MP3
138 0 0         if ($args{file} !~ /[Mm][Pp]3$/) {
139 0           $self->{error}=4;
140 0           $self->{errorString}='Not a MP3';
141 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
142 0           return undef;
143             }
144              
145             #makes sure the track is numeric
146 0 0 0       if (
147             defined($args{track}) &&
148             ($args{track} !~ /^[0123456789]*$/)
149             ) {
150 0           $self->{error}=5;
151 0           $self->{errorString}='Track is not numeric';
152 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
153 0           return undef;
154             }
155              
156             #makes sure the year is numeric
157 0 0 0       if (
158             defined($args{year}) &&
159             ($args{year} !~ /^[0123456789]*$/)
160             ) {
161 0           $self->{error}=5;
162 0           $self->{errorString}='Track is not numeric';
163 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
164 0           return undef;
165             }
166              
167 0           my $mp3=MP3::Tag->new($args{file});
168              
169 0           delete($args{file});
170              
171 0           $mp3->update_tags(\%args);
172              
173 0           return 1;
174             }
175              
176             =head2 rename
177              
178             This renames files. s/\//\\/g is used on all the tags to make sure
179             there are no directory issues.
180              
181             One argument is taken and it is a hash ref.
182              
183             The returned argument is a hash ref.
184              
185             =head3 args hash ref
186              
187             =head4 files
188              
189             This is a array of files to rename.
190              
191             =head4 template
192              
193             This is the template to use for renaming a file.
194              
195             The template keys are listed below.
196              
197             {$title}
198             {$track}
199             {$artist}
200             {$album}
201             {$comment}
202             {$year}
203             {$genre}
204              
205             The default template is.
206              
207             {$artist} - {$album} ({$year}) - {$track} - {$title}.mp3
208              
209             =head3 return hash ref
210              
211             =head4 failed
212              
213             This is a array of failed files.
214              
215             =head4 padto
216              
217             This pads a the track out to be this wide with zeros. By default is is 2.
218              
219             To disable this, set it to 0.
220              
221             =head4 success
222              
223             This is true if it succeeds.
224              
225             If it any thing failed, this is set to false.
226              
227             my $returned=$foo->rename(\%args);
228             if ( $foo->error || ){
229              
230             }
231              
232             =cut
233              
234             sub rename{
235 0     0 1   my $self=$_[0];
236 0           my %args;
237 0 0         if (defined($_[1])) {
238 0           %args=%{$_[1]};
  0            
239             }
240 0           my $method='rename';
241              
242             #blanks any previous errors
243 0 0         if (!$self->errorblank) {
244 0           warn($self->{module}.' '.$method.': Unable to blank previous error');
245 0           return undef;
246             }
247              
248 0 0         if (!defined($args{padto})) {
249 0           $args{padto}=2;
250             }
251              
252             #makes sure some files are specified.
253 0 0         if (!defined($args{files})) {
254 0           $self->{error}=1;
255 0           $self->{errorString}='No files specified';
256 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
257 0           return undef;
258             }
259 0 0         if (ref($args{files}) ne 'ARRAY') {
260 0           $self->{error}=2;
261 0           $self->{errorString}='The key files is not a array.';
262 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
263 0           return undef;
264             }
265 0 0         if (!defined($args{files}[0])) {
266 0           $self->{error}=1;
267 0           $self->{errorString}='No files specified';
268 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
269 0           return undef;
270             }
271              
272 0           my $template='{$artist} - {$album} ({$year}) - {$track} - {$title}.mp3';
273 0 0         if (defined($args{template})) {
274 0           $template=$args{template};
275             }
276              
277             #this will be returned
278 0           my $toreturn={failed=>[], success=>1,};
279              
280             #declare it here so it does not have to be constantly recreated
281 0           my $tobj = Text::NeatTemplate->new();
282              
283              
284 0           my $int=0;
285 0           while (defined( $args{files}[$int] )) {
286              
287 0 0 0       if (
288             (! -r $args{files}[$int] ) ||
289             ( $args{files}[$int] !~ /\.[Mm][Pp]3$/ )
290             ) {
291 0           $toreturn->{success}=0;
292 0           push( @{ $self->{failed} }, $args{file}[$int] );
  0            
293             }else {
294 0           my $mp3=MP3::Tag->new( $args{files}[$int] );
295 0           my ($title, $track, $artist, $album, $comment, $year, $genre) = $mp3->autoinfo();
296              
297 0           my $int2=length($track);
298 0           while ($int2 < $args{padto}) {
299 0           $track='0'.$track;
300              
301 0           $int2++;
302             }
303              
304 0           $track=~s/\/.*//;
305 0           $title=~s/\//\\/g;
306 0           $album=~s/\//\\/g;
307 0           $artist=~s/\//\\/g;
308 0           $genre=~s/\//\\/g;
309 0           $year=~s/\//\\/g;
310              
311 0           my %data=(
312             title=>$title,
313             track=>$track,
314             artist=>$artist,
315             album=>$album,
316             comment=>$comment,
317             year=>$year,
318             genre=>$genre,
319             );
320              
321 0           my $newfilename=$tobj->fill_in(
322             data_hash=>\%data,
323             template=>$template,
324             );
325              
326 0           rename($args{files}[$int], $newfilename);
327              
328             }
329              
330 0           $int++;
331             }
332              
333 0           return $toreturn;
334             }
335              
336             =head2 show
337              
338             This returns a string containing a description of all the specified MP3s.
339              
340             One argument is taken and it is a hash ref.
341              
342             The returned argument is a hash ref.
343              
344             =head3 args hash ref
345              
346             =head4 files
347              
348             This is a array of files to rename.
349              
350             =head4 template
351              
352             This is the template to use for renaming a file.
353              
354             The template keys are listed below.
355              
356             {$file}
357             {$title}
358             {$track}
359             {$artist}
360             {$album}
361             {$comment}
362             {$year}
363             {$genre}
364              
365             The default template is.
366              
367             File: {$file}
368             Artist: {$artist}
369             Album: {$album}
370             Year: {$year}
371             Track: {$track}
372             Title: {$title}
373              
374             =head3 return hash ref
375              
376             =head4 failed
377              
378             This is a array of failed files.
379              
380             =head4 padto
381              
382             This pads a the track out to be this wide with zeros. By default is is 2.
383              
384             To disable this, set it to 0.
385              
386             =head4 success
387              
388             This is true if it succeeds.
389              
390             If it any thing failed, this is set to false.
391              
392             my $returned=$foo->rename(\%args);
393             if ( $foo->error || ){
394              
395             }
396              
397             =cut
398              
399             sub show{
400 0     0 1   my $self=$_[0];
401 0           my %args;
402 0 0         if (defined($_[1])) {
403 0           %args=%{$_[1]};
  0            
404             }
405 0           my $method='rename';
406              
407             #blanks any previous errors
408 0 0         if (!$self->errorblank) {
409 0           warn($self->{module}.' '.$method.': Unable to blank previous error');
410 0           return undef;
411             }
412              
413 0 0         if (!defined($args{padto})) {
414 0           $args{padto}=2;
415             }
416              
417             #makes sure some files are specified.
418 0 0         if (!defined($args{files})) {
419 0           $self->{error}=1;
420 0           $self->{errorString}='No files specified';
421 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
422 0           return undef;
423             }
424 0 0         if (ref($args{files}) ne 'ARRAY') {
425 0           $self->{error}=2;
426 0           $self->{errorString}='The key files is not a array.';
427 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
428 0           return undef;
429             }
430 0 0         if (!defined($args{files}[0])) {
431 0           $self->{error}=1;
432 0           $self->{errorString}='No files specified';
433 0           warn($self->{module}.' '.$method.':'.$self->error.': '.$self->{errorString});
434 0           return undef;
435             }
436              
437 0           my $template="File: {\$file}\n".
438             "Artist: {\$artist}\n".
439             "Album: {\$album}\n".
440             "Year: {\$year}\n".
441             "Track: {\$track}\n".
442             "Title: {\$title}\n\n";
443 0 0         if (defined($args{template})) {
444 0           $template=$args{template};
445             }
446              
447             #this will be returned
448 0           my $toreturn={failed=>[], success=>1, show=>''};
449              
450             #declare it here so it does not have to be constantly recreated
451 0           my $tobj = Text::NeatTemplate->new();
452              
453 0           my $int=0;
454 0           while (defined( $args{files}[$int] )) {
455              
456 0 0 0       if (
457             (! -r $args{files}[$int] ) ||
458             ( $args{files}[$int] !~ /\.[Mm][Pp]3$/ )
459             ) {
460 0           $toreturn->{success}=0;
461 0           push( @{ $self->{failed} }, $args{file}[$int] );
  0            
462             }else {
463 0           my $mp3=MP3::Tag->new( $args{files}[$int] );
464 0           my ($title, $track, $artist, $album, $comment, $year, $genre) = $mp3->autoinfo();
465              
466 0           my $int2=length($track);
467 0           while ($int2 < $args{padto}) {
468 0           $track='0'.$track;
469              
470 0           $int2++;
471             }
472              
473 0           $track=~s/\/.*//;
474              
475 0           my %data=(
476             file=>$args{files}[$int],
477             title=>$title,
478             track=>$track,
479             artist=>$artist,
480             album=>$album,
481             comment=>$comment,
482             year=>$year,
483             genre=>$genre,
484             );
485              
486 0           $toreturn->{show}=$toreturn->{show}.$tobj->fill_in(
487             data_hash=>\%data,
488             template=>$template,
489             );
490             }
491              
492 0           $int++;
493             }
494              
495 0           return $toreturn;
496             }
497              
498             =head1 ERROR RELATED METHODS
499              
500             =head2 error
501              
502             This returns the current error value.
503              
504             This returns a integer or undefined, Perl boolean value, indicating if
505             a error is present or not and if it is which.
506              
507             if($foo->error){
508             print "Error Code: ".$foo->error."\n";
509             }
510              
511             =cut
512              
513             sub error{
514 0     0 1   return $_[0]->{error};
515             }
516              
517             =head2 errorString
518              
519             This turns the current error string.
520              
521             if($foo->errorString ne ''){
522             print "Error String: ".$foo->errorString."\n";
523             }
524              
525             =cut
526              
527             sub errorString{
528 0     0 1   return $_[0]->{errorString};
529             }
530              
531             =head2 errorblank
532              
533             This blanks a error, if a permanent error is not set.
534              
535             This is a internal method and there is no good reason to call it.
536              
537             =cut
538              
539             sub errorblank{
540 0 0   0 1   if ($_[0]->{perror}) {
541 0           warn($_[0]->{module}.' errorblank: Unable to blank error. A permanent one is set');
542 0           return undef;
543             }
544              
545 0           $_[0]->{error}=undef;
546 0           $_[0]->{errorString}='';
547              
548 0           return 1;
549             }
550              
551             =head1 ERROR CODES
552              
553             =head2 1
554              
555             No files specified.
556              
557             =head2 2
558              
559             The files key does not contain a array.
560              
561             =head2 3
562              
563             No changes specified.
564              
565             =head2 4
566              
567             Does not appear to be a MP3.
568              
569             =head2 5
570              
571             Track is not numeric.
572              
573             =head2 6
574              
575             Year is not numeric.
576              
577             =head1 AUTHOR
578              
579             Zane C. Bowers-Hadley, C<< >>
580              
581             =head1 BUGS
582              
583             Please report any bugs or feature requests to C, or through
584             the web interface at L. I will be notified, and then you'll
585             automatically be notified of progress on your bug as I make changes.
586              
587              
588              
589              
590             =head1 SUPPORT
591              
592             You can find documentation for this module with the perldoc command.
593              
594             perldoc MP3::Tag::Utils
595              
596              
597             You can also look for information at:
598              
599             =over 4
600              
601             =item * RT: CPAN's request tracker
602              
603             L
604              
605             =item * AnnoCPAN: Annotated CPAN documentation
606              
607             L
608              
609             =item * CPAN Ratings
610              
611             L
612              
613             =item * Search CPAN
614              
615             L
616              
617             =back
618              
619              
620             =head1 ACKNOWLEDGEMENTS
621              
622              
623             =head1 LICENSE AND COPYRIGHT
624              
625             Copyright 2012 Zane C. Bowers-Hadley.
626              
627             This program is free software; you can redistribute it and/or modify it
628             under the terms of either: the GNU General Public License as published
629             by the Free Software Foundation; or the Artistic License.
630              
631             See http://dev.perl.org/licenses/ for more information.
632              
633              
634             =cut
635              
636             1; # End of MP3::Tag::Utils