put back "use lib"
[id3fs.git] / bin / id3fs-tag
1 #!/usr/bin/perl -w
2 #
3 # id3fs - a FUSE-based filesystem for browsing audio metadata
4 # Copyright (C) 2010  Ian Beckwith <ianb@erislabs.net>
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 use lib '/home/ianb/projects/id3fs/id3fs/lib'; # FIXME: remove
20 use strict;
21 use Getopt::Long qw(Configure);
22 use ID3FS::AudioFile;
23 use vars qw($me);
24 $me=($0=~/(?:.*\/)?(.*)/)[0];
25
26 my $verbose=0;
27 my $help=0;
28 my ($artist, $album, $track, $tracknum, $year, $v1genre, $comment,
29     $delete_artist, $delete_album, $delete_track, $delete_tracknum,
30     $delete_year, $delete_v1genre, $delete_comment, $delete_all,
31     $delete_genre, $genre, $add_tags, $delete_tags, @replace_tags);
32
33 Configure(qw(bundling no_ignore_case));
34 my $optret=GetOptions(
35     "verbose|v"                    => \$verbose,
36     "help|h"                       => \$help,
37     "artist|a=s"                   => \$artist,
38     "album|l=s"                    => \$album,
39     "song|s=s"                     => \$track,
40     "tracknum|n=s"                 => \$tracknum,
41     "year|y=i"                     => \$year,
42     "v1genre|1=s"                  => \$v1genre,
43     "comment|c=s"                  => \$comment,
44     "delete-artist|A"              => \$delete_artist,
45     "delete-album|L"               => \$delete_album,
46     "delete-song|S"                => \$delete_track,
47     "delete-tracknum|N"            => \$delete_tracknum,
48     "delete-year|Y"                => \$delete_year,
49     "delete-v1genre|0"             => \$delete_v1genre,
50     "delete-comment|C"             => \$delete_comment,
51     "delete|delete-all|D"          => \$delete_all,
52     "delete-genre|G|delete-tags"   => \$delete_genre,
53     "genre|g|replace-all-tags|R=s" => \$genre,
54     "add-tags|tags|t=s"            => \$add_tags,
55     "delete-tags|T=s"              => \$delete_tags,
56     "replace-tags|r=s{2}"          => \@replace_tags,
57     );
58
59 usage() if(!@ARGV || !$optret || $help);
60
61 while(my $filename=shift @ARGV)
62 {
63     unless(-f $filename)
64     {
65         warn("$me: $filename: not found\n");
66         next;
67     }
68     my $file=ID3FS::AudioFile->new($filename);
69     my $changes=0;
70     $changes =  do_deletes($file);
71     $changes += do_adds($file);
72     if($changes)
73     {
74         do_write($file);
75     }
76     else
77     {
78         do_display($file);
79     }
80 }
81
82 sub do_deletes
83 {
84     my($file)=@_;
85     $file->delete_artist()           if($delete_artist);
86     $file->delete_album()            if($delete_album);
87     $file->delete_track()            if($delete_track);
88     $file->delete_tracknum()         if($delete_tracknum);
89     $file->delete_year()             if($delete_year);
90     $file->delete_v1genre()          if($delete_v1genre);
91     $file->delete_comment()          if($delete_comment);
92     $file->delete_all()              if($delete_all);
93     $file->delete_genre()            if($delete_genre);
94     $file->delete_tags($delete_tags) if($delete_tags);
95     if(@replace_tags && $replace_tags[0])
96     {
97         $file->delete_tags($replace_tags[0]);
98     }
99
100     return($delete_artist   || $delete_album  || $delete_track   ||
101            $delete_tracknum || $delete_year   || $delete_v1genre ||
102            $delete_comment  || $delete_all    || $delete_genre   ||
103            $delete_tags     || (@replace_tags && $replace_tags[0]));
104 }
105
106 sub do_adds
107 {
108     my($file)=@_;
109     $file->artist($artist)     if($artist);
110     $file->album($album)       if($album);
111     $file->track($track)       if($track);
112     $file->tracknum($tracknum) if($tracknum);
113     $file->year($year)         if($year);
114     $file->v1genre($v1genre)   if($v1genre);
115     $file->comment($comment)   if($comment);
116     $file->genre($genre)       if($genre);
117     $file->add_tags($add_tags) if($add_tags);
118     if(@replace_tags && $replace_tags[0])
119     {
120         $file->add_tags($replace_tags[1]);
121     }
122
123     return($artist  || $album || $track    || $tracknum || $year || $v1genre ||
124            $comment || $genre || $add_tags || (@replace_tags && $replace_tags[0]));
125 }
126
127 sub do_write
128 {
129     my($file)=@_;
130     $file->write(); 
131 }
132
133 sub do_display
134 {
135     my($file)=@_;
136 }
137
138 sub usage
139 {
140     die("Usage: $me [-vhALSNY0CDG] [-a ARTIST] [-l ALBUM] [-s SONG] [-n TRACKNUM] FILES...\n".
141         "       $me [-y YEAR] [-g GENRE] [-1 V1GENRE] [-c COMMENT] [--] FILES...\n".
142         "       $me [-t TAGS,TO,ADD] [-T TAGS,TO,DELETE]  FILES...\n".
143         "       $me [-r TAGS,TO,DELETE, TAGS,TO,ADD] [-R TAGS,TO,OVERWRITE,WITH] FILES...\n".
144
145         "  verbose|v                 \n".
146         "  help|h                 \n".
147         "  artist|a=s                 \n".
148         "  album|l=s                 \n".
149         "  song|s=s                 \n".
150         "  tracknum|n=s                 \n".
151         "  year|y=i                 \n".
152         "  v1genre|1=s                 \n".
153         "  comment|c=s                 \n".
154         "  delete-artist|A                 \n".
155         "  delete-album|L                 \n".
156         "  delete-song|S                 \n".
157         "  delete-tracknum|N                 \n".
158         "  delete-year|Y                 \n".
159         "  delete-v1genre|0                 \n".
160         "  delete-comment|C                 \n".
161         "  delete|delete-all|D                 \n".
162         "  delete-genre|G|delete-tags                 \n".
163         "  genre|g|replace-all-tags|R=s                 \n".
164         "  add-tags|tags|t=s                 \n".
165         "  delete-tags|T=s                 \n".
166         "  replace-tags|r=s{2}                 \n".
167
168         " -d|--dir=PATH              Base directory of source files (default: ARGV[0])\n".
169         " -f|--database=FILE         Path to database file (default: basedir/.id3fs)\n".
170         " -e|--extensions=EXT1,EXT2  File extensions to index (default: mp3, ogg, flac)\n".
171         " -l|list                    List tags in use\n" .
172         " -v|--verbose               Verbose\n".
173         " -h|--help                  This help\n".
174         " --                         End of options\n");
175 }
176
177 __END__
178
179 =head1 NAME
180
181 id3fs-index - Add files to id3fs index
182
183 =head1 SYNOPSIS
184
185 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>...]
186
187 =head1 DESCRIPTION
188
189 Extracts id3 tags from mp3 files (and comment tags from ogg and flac
190 files) and adds them to a sqlite database, ready for mounting
191 with L<id3fsd(8)>.
192
193 =head1 OPTIONS
194
195 =over 4
196
197 =item B<-l> | B<--list>
198
199 List tags in use in specified database.
200
201 =item S<B<-d >I<PATH>> | S<B<--dir=>I<PATH>>
202
203 Specify base directory of source files. All files will be indexed
204 relative to this point.
205
206 If not specified, defaults to the first non-option argument on the
207 command line. Note that to avoid ambiguities, if more than one
208 directory is specified on the command line, the base directory must
209 be specified explicitly.
210
211 All files indexed must be under the base directory.
212
213 =item S<B<-f >I<FILE>> | S<B<--database=>I<FILE>>
214
215 Database file to use. If not specified, defaults to
216 a hidden file called B<".id3fs"> under the base directory.
217
218 =item S<B<-e >I<EXT1,EXT2>> | S<B<--extensions=>I<EXT1,EXT2>>
219
220 File extensions to consider when indexing.
221 Defaults to B<.mp3>, B<.ogg> and B<.flac>.
222
223 =item B<-v>
224
225 Enable verbose operation.
226
227 =item B<-h>
228
229 Show a short help message.
230
231 =item B<-->
232
233 End of options.
234
235 =back
236
237 =head1 EXAMPLES
238
239 Index all files in the current directory:
240
241     id3fs-index .
242
243 Index current directory, printing each subdirectory as it recurses
244 into it:
245
246     id3fs-index -v .
247
248 Just index some sub-directories:
249
250     id3fs-index -d . dir1 dir2
251
252 Store the database in a custom location:
253
254     id3fs-index -f ~/.id3fs/index.sqlite .
255
256 Only index .mp3 and .flac files:
257
258     id3fs-index -e mp3,flac .
259
260 =head1 BUGS
261
262 Please report any found to ianb@erislabs.net
263
264 =head1 SEE ALSO
265
266 L<id3fsd(8)>, L<MP3::Tag>, L<Audio::Flac::Header>, L<Ogg::Vorbis::Header>
267
268 =head1 AUTHOR
269
270 Ian Beckwith <ianb@erislabs.net>
271
272 Many thanks to Aubrey Stark-Toller for help wrangling SQL.
273
274 =head1 AVAILABILITY
275
276 The latest version can be found at:
277
278 L<http://erislabs.net/ianb/projects/id3fs/>
279
280 =head1 COPYRIGHT
281
282 Copyright (C) 2010  Ian Beckwith <ianb@erislabs.net>
283
284 This program is free software: you can redistribute it and/or modify
285 it under the terms of the GNU General Public License as published by
286 the Free Software Foundation, either version 3 of the License, or
287 (at your option) any later version.
288
289 This program is distributed in the hope that it will be useful,
290 but WITHOUT ANY WARRANTY; without even the implied warranty of
291 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
292 GNU General Public License for more details.
293
294 You should have received a copy of the GNU General Public License
295 along with this program.  If not, see <http://www.gnu.org/licenses/>.
296
297 =cut