remove "use lib"
[id3fs.git] / sbin / id3fsd
index 8331e13..12808ed 100755 (executable)
@@ -1,12 +1,27 @@
 #!/usr/bin/perl -w
 #!/usr/bin/perl -w
-# Ian Beckwith <ianb@erislabs.net>
 #
 #
+# 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 lib '/home/ianb/projects/id3fs/id3fs/lib';
 use strict;
 use Getopt::Long qw(Configure);
 use ID3FS::DB;
 use ID3FS::Fuse;
 use strict;
 use Getopt::Long qw(Configure);
 use ID3FS::DB;
 use ID3FS::Fuse;
+use POSIX;
+
 use vars qw($me);
 $me=($0=~/(?:.*\/)?(.*)/)[0];
 
 use vars qw($me);
 $me=($0=~/(?:.*\/)?(.*)/)[0];
 
@@ -14,12 +29,15 @@ our $VERSION="1.00";
 my $verbose=0;
 my $help=0;
 my $dbpath=undef;
 my $verbose=0;
 my $help=0;
 my $dbpath=undef;
+my $tagdepth=undef;
 
 Configure(qw(bundling no_ignore_case));
 my $optret=GetOptions(
     "verbose|v"    => sub { $verbose++; },
     "help|h"       => \$help,
     "database|f=s" => \$dbpath,
 
 Configure(qw(bundling no_ignore_case));
 my $optret=GetOptions(
     "verbose|v"    => sub { $verbose++; },
     "help|h"       => \$help,
     "database|f=s" => \$dbpath,
+    "t|tagdepth=s" => \$tagdepth,
+    "o=s"          => sub {;}, # silently drop options passed by mount
     );
 
 usage() if(scalar(@ARGV) != 2 || !$optret || $help);
     );
 
 usage() if(scalar(@ARGV) != 2 || !$optret || $help);
@@ -27,18 +45,35 @@ usage() if(scalar(@ARGV) != 2 || !$optret || $help);
 my $source=shift;
 my $mountpoint=shift;
 
 my $source=shift;
 my $mountpoint=shift;
 
-my $db=ID3FS::DB->new($me, $verbose, 0, $dbpath, $source);
+my $db=ID3FS::DB->new($me, $verbose, 0, $source, $dbpath);
 exit unless($db);
 
 exit unless($db);
 
-my $fuse=ID3FS::Fuse->new($db, $source, $mountpoint, $verbose);
+my $fuse=ID3FS::Fuse->new($db, $source, $mountpoint, $verbose, $tagdepth);
+
+# disassociate from terminal
+unless($verbose)
+{
+    my $pid=fork();
+    if(defined($pid))
+    {
+       exit if($pid);   # parent
+       POSIX::setsid(); # child
+    }
+    else
+    {
+       print "$me: couldn't drop terminal: $!\n";
+    }
+}
+
 $fuse->run();
 
 sub usage
 {
 $fuse->run();
 
 sub usage
 {
-    die("Usage: $me [-vqh] [-f <dbfile>] [--] <sourcedir> <mountpoint>\n".
+    die("Usage: $me [-vh] [-f <dbfile>] [-t <tagdepth>] [--] <sourcedir> <mountpoint>\n".
+       " -t|--tagdepth=NUM\tMaximum number of tags in expression (default: 6)\n" .
+       " -f|--database=FILE\tPath to database file\n" .
        " -v\t\t\tVerbose (repeat for more verbosity)\n".
        " -h\t\t\tThis help\n".
        " -v\t\t\tVerbose (repeat for more verbosity)\n".
        " -h\t\t\tThis help\n".
-       " -f|--database=FILE\tPath to database file\n" .
        " --\t\t\tEnd of options\n");
 }
 
        " --\t\t\tEnd of options\n");
 }
 
@@ -57,6 +92,16 @@ B<id3fsd> [B<-vh>] S<B<[-f >I<dbfile>]> [B<-->] I<SOURCEDIR> I<MOUNTPOINT>
 id3fsd provides a browsable filesystem of your music files, organised
 into sub-directories by id3 tags (or flac/ogg comments).
 
 id3fsd provides a browsable filesystem of your music files, organised
 into sub-directories by id3 tags (or flac/ogg comments).
 
+id3fsd allows you to construct boolean queries from a tag folksonomy
+such as:
+
+  goth/AND/decade/1980s/
+  postrock/AND/NOT/rating/terrible/
+  thrash/OR/rapmetal/AND/NOT/wears-a-red-hat/
+  prog/AND/decade/1970s/OR/psychedelia/AND/decade/1960s/
+  location/sweden/AND/screamo/AND/postrock/
+
+Multiple tags can be stored in the genre tag, separated by commas.
 An index should first be created with L<id3fs-index(1)>, then id3fsd
 can mount the files in I<SOURCEDIR> on the directory I<MOUNTPOINT>.
 
 An index should first be created with L<id3fs-index(1)>, then id3fsd
 can mount the files in I<SOURCEDIR> on the directory I<MOUNTPOINT>.
 
@@ -66,52 +111,157 @@ at I<SOURCEDIR>/B<.id3fs>.
 The resulting filesystem is read-only. Tags appear as directories,
 and files appear as symlinks to the actual files in I<SOURCEDIR>.
 
 The resulting filesystem is read-only. Tags appear as directories,
 and files appear as symlinks to the actual files in I<SOURCEDIR>.
 
-FIXME: better description, allow_others/fuse.conf, fstab, explain genre tag
+=head1 QUICKSTART
+
+To mount a view of F<~/music> on F<~/tags>:
+
+  $ mkdir ~/tags
+  $ id3fs-index ~/music
+  $ id3fsd ~/music ~/tags
+
+You may need to be in the I<fuse> group, or be root.
 
 =head1 OPTIONS
 
 =over 4
 
 
 =head1 OPTIONS
 
 =over 4
 
-=item B<-v>
+=item I<SOURCEDIR>
 
 
-Enable verbose operation. Repeat for more verbosity.
+Directory containing actual audio files and database file F<.id3fs>
+(unless otherwise specified with B<-f>).
 
 
-=item B<-h>
+=item I<MOUNTPOINT>
 
 
-Show a short help message.
+Directory to mount the id3fs view of the files.
+
+=item S<B<-t >I<NUM>> | S<B<--tagdepth=>I<NUM>>
+
+Maximum number of tags in an expression. A query with many ANDs and
+NOTs can get quite slow. This option allows a cutoff before things get
+too slow, as well as providing some eventual limit when processes
+recurse into the filesystem. The default is 6.
 
 =item S<B<-f >I<FILE>> | S<B<--database=>I<FILE>>
 
 Use database in I<FILE>. The default is I<SOURCEDIR>/B<.id3fs>.
 
 
 =item S<B<-f >I<FILE>> | S<B<--database=>I<FILE>>
 
 Use database in I<FILE>. The default is I<SOURCEDIR>/B<.id3fs>.
 
+=item B<-v>
+
+Enable verbose operation. Repeat for more verbosity.  If verbose is
+enabled, id3fsd does not detach from the terminal.
+
+=item B<-h>
+
+Show a short help message.
+
 =item B<-->
 
 End of options.
 
 =back
 
 =item B<-->
 
 End of options.
 
 =back
 
-=head1 EXAMPLES
+=head1 FILESYSTEM LAYOUT
+
+A path in the filesystem consists of a tag query expression, followed
+by directories containing the matching files, arranged by artist and
+album.
+
+Example paths:
+
+  /krautrock/AND/year/1971/
+  /krautrock/AND/year/1971/Can
+  /krautrock/AND/year/1971/Can/Tago Mago/01-Paperhouse.mp3
+  /krautrock/AND/year/1971/Can/NOALBUM/Can - Oh Yeah (Live).mp3
+  /krautrock/AND/year/1971/Can/TRACKS/01-Paperhouse.mp3
+  /krautrock/AND/year/1971/Can/TRACKS/Can - Oh Yeah (Live).mp3
+  /krautrock/AND/year/1971/NOARTIST/unknown-track.mp3
+  /krautrock/AND/year/1971/TRACKS/01-Paperhouse.mp3
+
+id3fs supports OR, AND and NOT. NOT has the highest precedence,
+followed by AND, so F<foo/OR/NOT/bar/AND/baz> is parsed as
+(foo OR ((NOT bar) AND baz)).
+
+=head2 Tags
+
+Tags are extracted from the B<genre> tag of audio files with
+L<id3fs-index(1)>.
+
+Within the genre frame/comment, tags are separated by commas.
+
+Tags can have values, separated by a slash, eg I<metal/thrash>,
+I<rating/5>. Certain special tags are automatically filled in from
+other file metadata.
+
+=head2 Special Tags
+
+The following tags are automatically derived from other metadata in
+the audio files:
+
+=over 4
+
+=item B<year>
+
+Extracted from the B<year> or B<DATE> tag. If not found defaults to
+B<year/UNKNOWN>.
+
+=item B<decade>
+
+Also extracted from the B<year> or B<DATE> tag. If not found
+defaults to B<decade/UNKNOWN>.
+
+=item B<v1genre>
+
+If a mp3 file has an ID3V1.1 genre tag, its value is assigned to
+v1genre.
+
+=item B<audiotype>
+
+Type of audio file (mp3, ogg, flac). Always set.
+
+=back
+
+=head2 Special Directories
+
+=over 4
 
 
-To mount an id3fs filesystem which indexes B<~/music/albums> on
-B<~/music/tags>:
+=item B<TRACKS>
 
 
-First create the index:
+All tracks that match the given tag expression, whether they have an
+assigned artist and album or not.
 
 
-    id3fs-index -v ~/music/albums
+=item B<NOARTIST>
 
 
-If you have a large collection of music, this may take some time.
+Tracks matching the given expression that do not have an artist tag.
 
 
-Then create the mountpoint:
+=item B<NOALBUM>
 
 
-    mkdir ~/music/tags
+Tracks matching the given expression that do not have an album tag.
 
 
-and mount the filesystem:
+=item B<ALL>
 
 
-    id3fsd ~/music/albums ~/music/tags
+This is a special directory in the root of the filesystem, that
+provides access to all the indexed files, regardless of tags assigned.
 
 
-Then explore the tags in ~/music/tags/
+=back
 
 
-FIXME: fstab
+=head1 FUSE AND MOUNTING AUTOMATICALLY
+
+For others to be able to view your id3fs mount(s), you need to set the
+option B<user_allow_other> in F</etc/fuse.conf>.
+
+To mount a filesystem automatically, put an entry in F</etc/fstab>
+like:
+
+  id3fsd#/source/dir    /mount/point    defaults   0   0
+
+=head1 CAVEATS
+
+Because id3fs offers a combinatorial explosion of views of your files,
+processes recursing into the mount point will take a B<long> time to
+traverse it.
+
+Ensure your backups, cron jobs, F</etc/updatedb.conf>, etc. are
+configured to exclude the mount point.
 
 =head1 BUGS
 
 
 =head1 BUGS
 
@@ -125,19 +275,21 @@ L<id3fs-index(1)>, L<http://fuse.sourceforge.net>
 
 Ian Beckwith <ianb@erislabs.net>
 
 
 Ian Beckwith <ianb@erislabs.net>
 
+Many thanks to Aubrey Stark-Toller for help wrangling SQL.
+
 =head1 AVAILABILITY
 
 The latest version can be found at:
 
 =head1 AVAILABILITY
 
 The latest version can be found at:
 
-B<http://erislabs.net/ianb/projects/id3fs/>
+L<http://erislabs.net/ianb/projects/id3fs/>
 
 =head1 COPYRIGHT
 
 
 =head1 COPYRIGHT
 
-Copyright 2010 Ian Beckwith <ianb@erislabs.net>
+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
 
 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
+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,
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,