From: Ian Beckwith Date: Sat, 30 Oct 2010 00:27:03 +0000 (+0100) Subject: start id3fs-tag X-Git-Url: http://erislabs.net/gitweb/?p=id3fs.git;a=commitdiff_plain;h=f2202e8bd7e2eb7f73d684950d65422e4d965634 start id3fs-tag --- diff --git a/bin/id3fs-tag b/bin/id3fs-tag new file mode 100644 index 0000000..29cc455 --- /dev/null +++ b/bin/id3fs-tag @@ -0,0 +1,296 @@ +#!/usr/bin/perl -w +# +# id3fs - a FUSE-based filesystem for browsing audio metadata +# Copyright (C) 2010 Ian Beckwith +# +# 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 . + +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 [B<-lvh>] S<[B<-d >I]> S<[B<-f >I]> S<[B<-e >I]> [B<-->] [I...] + +=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. + +=head1 OPTIONS + +=over 4 + +=item B<-l> | B<--list> + +List tags in use in specified database. + +=item SI> | SI> + +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 SI> | SI> + +Database file to use. If not specified, defaults to +a hidden file called B<".id3fs"> under the base directory. + +=item SI> | SI> + +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, L, L, L + +=head1 AUTHOR + +Ian Beckwith + +Many thanks to Aubrey Stark-Toller for help wrangling SQL. + +=head1 AVAILABILITY + +The latest version can be found at: + +L + +=head1 COPYRIGHT + +Copyright (C) 2010 Ian Beckwith + +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 . + +=cut