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; |