--- /dev/null
+#!/usr/bin/perl -w
+#
+# id3fs - a FUSE-based filesystem for browsing audio metadata
+# Copyright (C) 2010 Ian Beckwith <ianb@erislabs.net>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+use strict;
+use Getopt::Long qw(Configure);
+use ID3FS::AudioFile;
+use vars qw($me);
+$me=($0=~/(?:.*\/)?(.*)/)[0];
+
+my $verbose=0;
+my $help=0;
+my ($artist, $album, $track, $tracknum, $year, $v1genre, $comment,
+ $delete_artist, $delete_album, $delete_track, $delete_tracknum,
+ $delete_year, $delete_v1genre, $delete_comment, $delete_all,
+ $delete_genre, $genre, $add_tags, $delete_tags, @replace_tags);
+
+Configure(qw(bundling no_ignore_case));
+my $optret=GetOptions(
+ "verbose|v" => \$verbose,
+ "help|h" => \$help,
+ "artist|a=s" => \$artist,
+ "album|l=s" => \$album,
+ "song|s=s" => \$track,
+ "tracknum|n=s" => \$tracknum,
+ "year|y=i" => \$year,
+ "v1genre|1=s" => \$v1genre,
+ "comment|c=s" => \$comment,
+ "delete-artist|A" => \$delete_artist,
+ "delete-album|L" => \$delete_album,
+ "delete-song|S" => \$delete_track,
+ "delete-tracknum|N" => \$delete_tracknum,
+ "delete-year|Y" => \$delete_year,
+ "delete-v1genre|0" => \$delete_v1genre,
+ "delete-comment|C" => \$delete_comment,
+ "delete|delete-all|D" => \$delete_all,
+ "delete-genre|G|delete-tags" => \$delete_genre,
+ "genre|g|replace-all-tags|R=s" => \$genre,
+ "add-tags|tags|t=s" => \$add_tags,
+ "delete-tags|T=s" => \$delete_tags,
+ "replace-tags|r=s{2}" => \@replace_tags,
+ );
+
+usage() if(!@ARGV || !$optret || $help);
+
+while(my $filename=shift @ARGV)
+{
+ unless(-f $filename)
+ {
+ warn("$me: $filename: not found\n");
+ next;
+ }
+ my $file=ID3FS::AudioFile->new($filename);
+ my $changes=0;
+ $changes = do_deletes($file);
+ $changes += do_adds($file);
+ if($changes)
+ {
+ do_write($file);
+ }
+ else
+ {
+ do_display($file);
+ }
+}
+
+sub do_deletes
+{
+ my($file)=@_;
+ $file->delete_artist() if($delete_artist);
+ $file->delete_album() if($delete_album);
+ $file->delete_track() if($delete_track);
+ $file->delete_tracknum() if($delete_tracknum);
+ $file->delete_year() if($delete_year);
+ $file->delete_v1genre() if($delete_v1genre);
+ $file->delete_comment() if($delete_comment);
+ $file->delete_all() if($delete_all);
+ $file->delete_genre() if($delete_genre);
+ $file->delete_tags($delete_tags) if($delete_tags);
+ if(@replace_tags && $replace_tags[0])
+ {
+ $file->delete_tags($replace_tags[0]);
+ }
+
+ return($delete_artist || $delete_album || $delete_track ||
+ $delete_tracknum || $delete_year || $delete_v1genre ||
+ $delete_comment || $delete_all || $delete_genre ||
+ $delete_tags || (@replace_tags && $replace_tags[0]));
+}
+
+sub do_adds
+{
+ my($file)=@_;
+ $file->artist($artist) if($artist);
+ $file->album($album) if($album);
+ $file->track($track) if($track);
+ $file->tracknum($tracknum) if($tracknum);
+ $file->year($year) if($year);
+ $file->v1genre($v1genre) if($v1genre);
+ $file->comment($comment) if($comment);
+ $file->genre($genre) if($genre);
+ $file->add_tags($add_tags) if($add_tags);
+ if(@replace_tags && $replace_tags[0])
+ {
+ $file->add_tags($replace_tags[1]);
+ }
+
+ return($artist || $album || $track || $tracknum || $year || $v1genre ||
+ $comment || $genre || $add_tags || (@replace_tags && $replace_tags[0]));
+}
+
+sub do_write
+{
+ my($file)=@_;
+ $file->write();
+}
+
+sub do_display
+{
+ my($file)=@_;
+}
+
+sub usage
+{
+ die("Usage: $me [-vhALSNY0CDG] [-a ARTIST] [-l ALBUM] [-s SONG] [-n TRACKNUM] FILES...\n".
+ " $me [-y YEAR] [-g GENRE] [-1 V1GENRE] [-c COMMENT] [--] FILES...\n".
+ " $me [-t TAGS,TO,ADD] [-T TAGS,TO,DELETE] FILES...\n".
+ " $me [-r TAGS,TO,DELETE, TAGS,TO,ADD] [-R TAGS,TO,OVERWRITE,WITH] FILES...\n".
+
+ " verbose|v \n".
+ " help|h \n".
+ " artist|a=s \n".
+ " album|l=s \n".
+ " song|s=s \n".
+ " tracknum|n=s \n".
+ " year|y=i \n".
+ " v1genre|1=s \n".
+ " comment|c=s \n".
+ " delete-artist|A \n".
+ " delete-album|L \n".
+ " delete-song|S \n".
+ " delete-tracknum|N \n".
+ " delete-year|Y \n".
+ " delete-v1genre|0 \n".
+ " delete-comment|C \n".
+ " delete|delete-all|D \n".
+ " delete-genre|G|delete-tags \n".
+ " genre|g|replace-all-tags|R=s \n".
+ " add-tags|tags|t=s \n".
+ " delete-tags|T=s \n".
+ " replace-tags|r=s{2} \n".
+
+ " -d|--dir=PATH Base directory of source files (default: ARGV[0])\n".
+ " -f|--database=FILE Path to database file (default: basedir/.id3fs)\n".
+ " -e|--extensions=EXT1,EXT2 File extensions to index (default: mp3, ogg, flac)\n".
+ " -l|list List tags in use\n" .
+ " -v|--verbose Verbose\n".
+ " -h|--help This help\n".
+ " -- End of options\n");
+}
+
+__END__
+
+=head1 NAME
+
+id3fs-index - Add files to id3fs index
+
+=head1 SYNOPSIS
+
+B<id3fs-index> [B<-lvh>] S<[B<-d >I<basedir>]> S<[B<-f >I<dbpath>]> S<[B<-e >I<mp3,ogg,flac>]> [B<-->] [I<DIR>...]
+
+=head1 DESCRIPTION
+
+Extracts id3 tags from mp3 files (and comment tags from ogg and flac
+files) and adds them to a sqlite database, ready for mounting
+with L<id3fsd(8)>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-l> | B<--list>
+
+List tags in use in specified database.
+
+=item S<B<-d >I<PATH>> | S<B<--dir=>I<PATH>>
+
+Specify base directory of source files. All files will be indexed
+relative to this point.
+
+If not specified, defaults to the first non-option argument on the
+command line. Note that to avoid ambiguities, if more than one
+directory is specified on the command line, the base directory must
+be specified explicitly.
+
+All files indexed must be under the base directory.
+
+=item S<B<-f >I<FILE>> | S<B<--database=>I<FILE>>
+
+Database file to use. If not specified, defaults to
+a hidden file called B<".id3fs"> under the base directory.
+
+=item S<B<-e >I<EXT1,EXT2>> | S<B<--extensions=>I<EXT1,EXT2>>
+
+File extensions to consider when indexing.
+Defaults to B<.mp3>, B<.ogg> and B<.flac>.
+
+=item B<-v>
+
+Enable verbose operation.
+
+=item B<-h>
+
+Show a short help message.
+
+=item B<-->
+
+End of options.
+
+=back
+
+=head1 EXAMPLES
+
+Index all files in the current directory:
+
+ id3fs-index .
+
+Index current directory, printing each subdirectory as it recurses
+into it:
+
+ id3fs-index -v .
+
+Just index some sub-directories:
+
+ id3fs-index -d . dir1 dir2
+
+Store the database in a custom location:
+
+ id3fs-index -f ~/.id3fs/index.sqlite .
+
+Only index .mp3 and .flac files:
+
+ id3fs-index -e mp3,flac .
+
+=head1 BUGS
+
+Please report any found to ianb@erislabs.net
+
+=head1 SEE ALSO
+
+L<id3fsd(8)>, L<MP3::Tag>, L<Audio::Flac::Header>, L<Ogg::Vorbis::Header>
+
+=head1 AUTHOR
+
+Ian Beckwith <ianb@erislabs.net>
+
+Many thanks to Aubrey Stark-Toller for help wrangling SQL.
+
+=head1 AVAILABILITY
+
+The latest version can be found at:
+
+L<http://erislabs.net/ianb/projects/id3fs/>
+
+=head1 COPYRIGHT
+
+Copyright (C) 2010 Ian Beckwith <ianb@erislabs.net>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+=cut