File Coverage

blib/lib/File/Find/Rule/MP3Info.pm
Criterion Covered Total %
statement 34 34 100.0
branch 18 20 90.0
condition 2 3 66.6
subroutine 8 8 100.0
pod 0 1 0.0
total 62 66 93.9


line stmt bran cond sub pod time code
1             package File::Find::Rule::MP3Info;
2 1     1   771 use strict;
  1         3  
  1         34  
3              
4 1     1   1024 use File::Find::Rule;
  1         9775  
  1         10  
5 1     1   54 use base qw( File::Find::Rule );
  1         6  
  1         159  
6 1     1   6 use vars qw( @EXPORT $VERSION );
  1         1  
  1         78  
7             @EXPORT = @File::Find::Rule::EXPORT;
8             $VERSION = '0.01';
9              
10 1     1   1418 use MP3::Info;
  1         50302  
  1         106  
11 1     1   10 use Number::Compare;
  1         2  
  1         491  
12              
13             =head1 NAME
14              
15             File::Find::Rule::MP3Info - rule to match on id3 tags, length, bitrate, etc
16              
17             =head1 SYNOPSIS
18              
19             use File::Find::Rule::MP3Info;
20              
21             # Which mp3s haven't I set the artist tag on yet?
22             my @mp3s = find( mp3info => { ARTIST => '' }, in => '/mp3' );
23              
24             # Or be OO.
25             @mp3s = File::Find::Rule::MP3Info->file()
26             ->mp3info( TITLE => 'Paper Bag' )
27             ->in( '/mp3' );
28              
29             # What have I got that's 3 minutes or longer?
30             @mp3s = File::Find::Rule::MP3Info->file()
31             ->mp3info( MM => '>=3' )
32             ->in( '/mp3' );
33              
34             # What have I got by either Kristin Hersh or Throwing Muses?
35             # I'm sometimes lazy about case in my tags.
36             @mp3s = find( mp3info =>
37             { ARTIST => qr/(kristin hersh|throwing muses)/i },
38             in => '/mp3' );
39              
40             =head1 DESCRIPTION
41              
42             An interface between MP3::Info and File::Find::Rule to let you find
43             files based on MP3-specific information such as bitrate, frequency,
44             playing time, the stuff in the ID3 tag, and so on.
45              
46             =head1 METHODS
47              
48             =head2 B
49              
50             my @mp3s = find( mp3info => { YEAR => '1990' }, in => '/mp3' );
51              
52             Only matches when I criteria are met. You can be OO or
53             procedural as you please, as per File::Find::Rule.
54              
55             The criteria you can use are those that are returned by the
56             C and C methods of MP3::Info.
57              
58             The following fields are treated as numeric and so can be matched
59             against using Number::Compare comparisons: YEAR, BITRATE, FREQUENCY,
60             SIZE, SECS, MM, SS, MS, FRAMES, FRAME_LENGTH, VBR_SCALE.
61              
62             The following fields are treated as strings and so can be matched
63             against with either an exact match or a qr// regex: TITLE, ARTIST,
64             ALBUM, COMMENT, GENRE.
65              
66             Anything else is matched against as an exact match.
67              
68             Let's make it DTRT with boolean fields, next!
69              
70             This needs benchmarking; will it be impossibly slow with lots of files?
71             I'm seeing around a minute or so to go through 6 gig.
72              
73             =cut
74              
75             my %numeric = map { $_ => 1 } qw( YEAR BITRATE FREQUENCY SIZE SECS MM SS MS
76             FRAMES FRAME_LENGTH VBR_SCALE );
77             my %strings = map { $_ => 1 } qw( TITLE ARTIST ALBUM COMMENT GENRE );
78              
79             sub File::Find::Rule::mp3info {
80 11     11 0 21918 my $self = shift()->_force_object;
81              
82             # Procedural interface allows passing arguments as a hashref.
83 11 100       157 my %criteria = UNIVERSAL::isa($_[0], "HASH") ? %{$_[0]} : @_;
  5         29  
84              
85             $self->exec( sub {
86 60     60   33300 my $file = shift;
87 60 50       337 my $info = get_mp3info($file) or return;
88 60 100       250672 my $tag = get_mp3tag($file) or return;
89 44         58115 for my $fld (keys %criteria) {
90             # Field can be in id3tag, other info, or not defined.
91 50 100       360 my $value =
92             defined $tag->{$fld} ? $tag->{$fld} : $info->{$fld};
93 50 50       284 return unless defined $value;
94              
95 50 100 66     369 if ( $numeric{$fld} ) {
    100          
96 24         314 my $cmp = Number::Compare->new($criteria{$fld});
97 24 100       7396 return unless $cmp->($value);
98             } elsif ( $strings{$fld}
99             and ref $criteria{$fld} eq 'Regexp') {
100 8 100       731 return unless $value =~ /$criteria{$fld}/;
101             } else {
102 18 100       477 return unless $value eq $criteria{$fld};
103             }
104             }
105 17         893 return 1;
106 11         323 } );
107             }
108              
109             =head1 AUTHOR
110              
111             Kake Pugh , from an idea by Paul Mison, all the real
112             work previously done by Richard Clamp in File::Find::Rule and Chris
113             Nandor in MP3::Info.
114              
115             =head1 FEEDBACK
116              
117             Send me mail; it makes me happy. Does this suck? Why? Does it rock?
118             Why?
119              
120             =head1 COPYRIGHT
121              
122             Copyright (C) 2002 Kate L Pugh. All Rights Reserved.
123              
124             This module is free software; you can redistribute it and/or modify it
125             under the same terms as Perl itself.
126              
127             =head1 SEE ALSO
128              
129             File::Find::Rule
130             MP3::Info
131              
132             =cut
133              
134             1;