Changeset 10 in mp3-find for trunk/lib/MP3/Find
- Timestamp:
- 02/02/06 01:51:00 (19 years ago)
- Location:
- trunk/lib/MP3/Find
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/lib/MP3/Find/Base.pm
r7 r10 93 93 =head1 NAME 94 94 95 MP3::Find::Base - Base class for MP3::Find finders95 MP3::Find::Base - Base class for MP3::Find backends 96 96 97 97 =head1 SYNOPSIS -
trunk/lib/MP3/Find/DB.pm
r3 r10 5 5 6 6 use base qw(MP3::Find::Base); 7 use Carp; 7 8 8 9 use DBI; … … 11 12 my $sql = SQL::Abstract->new; 12 13 14 my @COLUMNS = ( 15 [ mtime => 'INTEGER' ], # the filesystem mtime, so we can do incremental updates 16 [ FILENAME => 'TEXT' ], 17 [ TITLE => 'TEXT' ], 18 [ ARTIST => 'TEXT' ], 19 [ ALBUM => 'TEXT' ], 20 [ YEAR => 'INTEGER' ], 21 [ COMMENT => 'TEXT' ], 22 [ GENRE => 'TEXT' ], 23 [ TRACKNUM => 'INTEGER' ], 24 [ VERSION => 'NUMERIC' ], 25 [ LAYER => 'INTEGER' ], 26 [ STEREO => 'TEXT' ], 27 [ VBR => 'TEXT' ], 28 [ BITRATE => 'INTEGER' ], 29 [ FREQUENCY => 'INTEGER' ], 30 [ SIZE => 'INTEGER' ], 31 [ OFFSET => 'INTEGER' ], 32 [ SECS => 'INTEGER' ], 33 [ MM => 'INTEGER' ], 34 [ SS => 'INTEGER' ], 35 [ MS => 'INTEGER' ], 36 [ TIME => 'TEXT' ], 37 [ COPYRIGHT => 'TEXT' ], 38 [ PADDING => 'INTEGER' ], 39 [ MODE => 'INTEGER' ], 40 [ FRAMES => 'INTEGER' ], 41 [ FRAME_LENGTH => 'INTEGER' ], 42 [ VBR_SCALE => 'INTEGER' ], 43 ); 44 45 13 46 sub search { 14 47 my $self = shift; 15 48 my ($query, $dirs, $sort, $options) = @_; 16 49 17 my $dbh = DBI->connect("dbi:SQLite:dbname=$$options{db_file}", '', ''); 50 croak 'Need a database name to search (set "db_file" in the call to find_mp3s)' unless $$options{db_file}; 51 52 my $dbh = DBI->connect("dbi:SQLite:dbname=$$options{db_file}", '', '', {RaiseError => 1}); 18 53 19 54 # use the 'LIKE' operator to ignore case … … 43 78 44 79 return @results; 80 } 81 82 sub create_db { 83 my $self = shift; 84 my $db_file = shift or croak "Need a name for the database I'm about to create"; 85 my $dbh = DBI->connect("dbi:SQLite:dbname=$db_file", '', '', {RaiseError => 1}); 86 $dbh->do('CREATE TABLE mp3 (' . join(',', map { "$$_[0] $$_[1]" } @COLUMNS) . ')'); 87 } 88 89 sub update_db { 90 my $self = shift; 91 my $db_file = shift or croak "Need the name of the databse to update"; 92 my $dirs = shift; 93 94 my @dirs = ref $dirs eq 'ARRAY' ? @$dirs : ($dirs); 95 96 my $dbh = DBI->connect("dbi:SQLite:dbname=$db_file", '', '', {RaiseError => 1}); 97 my $mtime_sth = $dbh->prepare('SELECT mtime FROM mp3 WHERE FILENAME = ?'); 98 my $insert_sth = $dbh->prepare( 99 'INSERT INTO mp3 (' . 100 join(',', map { $$_[0] } @COLUMNS) . 101 ') VALUES (' . 102 join(',', map { '?' } @COLUMNS) . 103 ')' 104 ); 105 my $update_sth = $dbh->prepare( 106 'UPDATE mp3 SET ' . 107 join(',', map { "$$_[0] = ?" } @COLUMNS) . 108 ' WHERE FILENAME = ?' 109 ); 110 111 # the number of records added or updated 112 my $count = 0; 113 114 # look for mp3s using the filesystem backend 115 require MP3::Find::Filesystem; 116 my $finder = MP3::Find::Filesystem->new; 117 for my $mp3 ($finder->find_mp3s(dir => \@dirs, no_format => 1)) { 118 # see if the file has been modified since it was first put into the db 119 $mp3->{mtime} = (stat($mp3->{FILENAME}))[9]; 120 $mtime_sth->execute($mp3->{FILENAME}); 121 my $records = $mtime_sth->fetchall_arrayref; 122 123 warn "Multiple records for $$mp3{FILENAME}\n" if @$records > 1; 124 125 if (@$records == 0) { 126 $insert_sth->execute(map { $mp3->{$$_[0]} } @COLUMNS); 127 print STDERR "A $$mp3{FILENAME}\n"; 128 $count++; 129 } elsif ($mp3->{mtime} > $$records[0][0]) { 130 # the mp3 file is newer than its record 131 $update_sth->execute((map { $mp3->{$$_[0]} } @COLUMNS), $mp3->{FILENAME}); 132 print STDERR "U $$mp3{FILENAME}\n"; 133 $count++; 134 } 135 } 136 137 # as a workaround for the 'closing dbh with active staement handles warning 138 # (see http://rt.cpan.org/Ticket/Display.html?id=9643#txn-120724) 139 foreach ($mtime_sth, $insert_sth, $update_sth) { 140 $_->{Active} = 1; 141 $_->finish; 142 } 143 144 return $count; 145 } 146 147 sub destroy_db { 148 my $self = shift; 149 my $db_file = shift or croak "Need the name of a database to destory"; 150 unlink $db_file; 45 151 } 46 152 … … 64 170 }, 65 171 ignore_case => 1, 66 ); 172 db_file => 'mp3.db', 173 ); 174 175 # you can do things besides just searching the database 176 177 # create another database 178 $finder->create_db('my_mp3s.db'); 179 180 # update the database from the filesystem 181 $finder->update_db('my_mp3s.db', ['/home/peter/mp3', '/home/peter/cds']); 182 183 # and then blow it away 184 $finder->destroy_db('my_mp3s.db'); 67 185 68 186 =head1 REQUIRES … … 121 239 =back 122 240 241 =head1 METHODS 242 243 =head2 create_db 244 245 $finder->create_db($db_filename); 246 247 Creates a SQLite database in the file named c<$db_filename>. 248 249 =head2 update_db 250 251 my $count = $finder->update_db($db_filename, \@dirs); 252 253 Searches for all mp3 files in the directories named by C<@dirs> 254 using L<MP3::Find::Filesystem>, and adds or updates the ID3 info 255 from those files to the database. If a file already has a record 256 in the database, then it will only be updated if it has been modified 257 sinc ethe last time C<update_db> was run. 258 259 =head2 destroy_db 260 261 $finder->destroy_db($db_filename); 262 263 Permanantly removes the database. 264 123 265 =head1 TODO 124 266 125 Move the database/table creation code from F<mp3db> into this126 module.127 128 267 Database maintanence routines (e.g. clear out old entries) 129 268 269 Allow the passing of a DSN or an already created C<$dbh> instead 270 of a SQLite database filename. 271 130 272 =head1 SEE ALSO 131 273 132 L<MP3::Find>, L<MP3::Find:: DB>274 L<MP3::Find>, L<MP3::Find::Filesystem>, L<mp3db> 133 275 134 276 =head1 AUTHOR
Note: See TracChangeset
for help on using the changeset viewer.