source: mp3-find/trunk/lib/MP3/Find/Base.pm @ 39

Last change on this file since 39 was 39, checked in by peter, 13 years ago

Add the META.yml metadata file to version control

File size: 5.4 KB
Line 
1package MP3::Find::Base;
2
3use strict;
4use warnings;
5
6use Carp;
7
8#TODO: allow ID3v2 tags in printf format
9my %format_codes = (
10    a => 'ARTIST',
11    t => 'TITLE',
12    b => 'ALBUM',
13    n => 'TRACKNUM',
14    y => 'YEAR',
15    g => 'GENRE',
16);
17
18sub new {
19    my $invocant = shift;
20    my $class = ref $invocant || $invocant;
21    my %options = @_;
22    my $self = \%options;
23    bless $self, $class;
24}
25
26sub find_mp3s {
27    my $self = shift;
28    my %opt = @_;
29   
30    my $dir = $opt{dir} || $ENV{HOME};
31    my @DIRS = ref $dir eq 'ARRAY' ? @$dir : ($dir);
32   
33    my %QUERY = %{ $opt{query} || {} };
34   
35    # array ref for multiple sort fields, but allow
36    # a simple scalar for single values
37    my @SORT = $opt{sort} ? 
38        (ref $opt{sort} eq 'ARRAY' ? @{ $opt{sort} } : ($opt{sort})) :
39        ();
40   
41    foreach (keys %QUERY) {
42        if (defined $QUERY{$_}) {
43            # package everything uniformly, so subclasses don't need to unpack it
44            $QUERY{$_} = [ $QUERY{$_} ] unless ref $QUERY{$_} eq 'ARRAY';
45        } else {
46            # so we don't have spurious warnings when trying to match against undef       
47            delete $QUERY{$_};
48        }
49    }
50   
51    # do the search
52    my @results = $self->search(\%QUERY, \@DIRS, \@SORT, \%opt);
53   
54    # maybe they want the unformatted data
55    return @results if $opt{no_format};
56   
57    if ($opt{printf}) {
58        # printf style output format
59        foreach (@results) {
60            my $output = $opt{printf};
61            for my $code (keys %format_codes) {
62               
63                while ($output =~ m/%((-\d)?\d*)$code/g) {
64                    # field size modifier
65                    my $modifier = $1 || '';
66                    # figure out the size of the formating code
67                    my $code_size = 2 + length($modifier);
68                    my $value = sprintf("%${modifier}s", $_->{$format_codes{$code}} || '');
69                    substr($output, pos($output) - $code_size, $code_size, $value);
70                }
71            }
72            # to allow literal '%'
73            $output =~ s/%%/%/g;       
74            $_ = $output;
75        }
76    } else {
77        # just the filenames, please
78        @results = map { $_->{FILENAME} } @results;
79    }
80   
81    return @results;
82}
83
84sub search {
85    croak "Method 'search' not implemented in " . __PACKAGE__;
86}
87
88# module return
891;
90
91=head1 NAME
92
93MP3::Find::Base - Base class for MP3::Find backends
94
95=head1 SYNOPSIS
96
97    package MyFinder;
98    use base 'MP3::Find::Base';
99   
100    sub search {
101        my $self = shift;
102        my ($query, $dirs, $sort, $options) = @_;
103       
104        # do something to find and sort the mp3s...
105        my @results = do_something(...);
106       
107        return @results;
108    }
109   
110    package main;
111    my $finder = MyFinder->new;
112   
113    # see MP3::Find for details about %options
114    print "$_\n" foreach $finder->find_mp3s(\%options);       
115
116=head1 DESCRIPTION
117
118This is the base class for the classes that actually do the
119searching and sorting for L<MP3::Find>.
120
121=head1 METHODS
122
123=head2 new
124
125Really simple constructor. If you pass it a hash of options, it
126will hang on to them for you.
127
128=head2 search
129
130This is the one you should override in your subclass. If you
131don't, the base class C<search> method will croak.
132
133The C<search> method is called by the C<find_mp3s> method with
134the following arguments: the finder object, a hashref of query
135parameters, an arrayref of directories to search, and a hashref
136of miscellaneous options.
137
138The search method should return a list of hashrefs representing
139the results of the search. Each hashref should have the following
140keys (all except C<FILENAME> are derived from the keys returned
141by the C<get_mp3tag> and C<get_mp3Info> functions from L<MP3::Info>):
142
143    FILENAME
144   
145    TITLE
146    ARTIST
147    ALBUM
148    YEAR
149    COMMENT
150    GENRE
151    TRACKNUM
152   
153    VERSION         -- MPEG audio version (1, 2, 2.5)
154    LAYER           -- MPEG layer description (1, 2, 3)
155    STEREO          -- boolean for audio is in stereo
156   
157    VBR             -- boolean for variable bitrate
158    BITRATE         -- bitrate in kbps (average for VBR files)
159    FREQUENCY       -- frequency in kHz
160    SIZE            -- bytes in audio stream
161    OFFSET          -- bytes offset that stream begins
162   
163    SECS            -- total seconds
164    MM              -- minutes
165    SS              -- leftover seconds
166    MS              -- leftover milliseconds
167    TIME            -- time in MM:SS
168   
169    COPYRIGHT       -- boolean for audio is copyrighted
170    PADDING         -- boolean for MP3 frames are padded
171    MODE            -- channel mode (0 = stereo, 1 = joint stereo,
172                    -- 2 = dual channel, 3 = single channel)
173    FRAMES          -- approximate number of frames
174    FRAME_LENGTH    -- approximate length of a frame
175    VBR_SCALE       -- VBR scale from VBR header
176
177
178=head2 find_mp3s
179
180The method that should be called by the program doing the searching.
181
182See L<MP3::Find> for an explanation of the options that can be passed
183to C<find_mp3s>.
184
185=head1 TODO
186
187More format codes? Possibly look into using L<String::Format>
188
189=head1 SEE ALSO
190
191L<MP3::Find>, L<MP3::Find::Filesystem>, L<MP3::Find::DB>
192
193See L<MP3::Info> for more information about the fields you can
194search and sort on.
195
196=head1 AUTHOR
197
198Peter Eichman <peichman@cpan.org>
199
200=head1 COPYRIGHT AND LICENSE
201
202Copyright (c) 2006 by Peter Eichman. All rights reserved.
203
204This program is free software; you can redistribute it and/or
205modify it under the same terms as Perl itself.
206
207=cut
Note: See TracBrowser for help on using the repository browser.