X-Git-Url: https://erislabs.net/gitweb/?a=blobdiff_plain;f=bin%2Fid3fs-tag;h=9ed8aaced7efe4b1f4b49da120232cb08ba97fc8;hb=a88e7ff8c0d20c928dbe6ea52c779454779d2366;hp=28b4b6a21d1db7d1129de9025ad2bc131545b2df;hpb=262b921378f9edb0a4f0931047fd35232dce78fa;p=id3fs.git diff --git a/bin/id3fs-tag b/bin/id3fs-tag index 28b4b6a..9ed8aac 100755 --- a/bin/id3fs-tag +++ b/bin/id3fs-tag @@ -19,17 +19,20 @@ use lib '/home/ianb/projects/id3fs/id3fs/lib'; # FIXME: remove use strict; use Getopt::Long qw(Configure); +use File::Find; use ID3FS::AudioFile; use vars qw($me); $me=($0=~/(?:.*\/)?(.*)/)[0]; +my @extensions=qw(mp3); # FIXME: flac ogg +my (%file_tags); 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, $overwrite_tagvals, - $delete_tagvals); + $delete_tagvals, $tag_summary); Configure(qw(bundling no_ignore_case)); my $optret=GetOptions( @@ -56,29 +59,50 @@ my $optret=GetOptions( "overwrite-tagvals|tagvals|o=s" => \$overwrite_tagvals, "delete-tags|T=s" => \$delete_tags, "delete-tags-with-values|O=s" => \$delete_tagvals, + "summary|V" => \$tag_summary, ); usage() if(!@ARGV || !$optret || $help); -while(my $filename=shift @ARGV) +while(my $path=shift @ARGV) { - unless(-f $filename) + unless(-e $path) { - warn("$me: $filename: not found\n"); + warn("$me: $path: not found\n"); next; } - my $file=ID3FS::AudioFile->new($filename); - next unless($file); - my $changes=0; - $changes = do_deletes($file); - $changes += do_adds($file); - if($changes) - { - do_write($file); - } - else + File::Find::find( {wanted => \&wanted, follow => 1, no_chdir => 1}, $path); +} + +summarize_tags() if($tag_summary); + + +sub wanted +{ + my $ext=''; + if(/.*\.(.*)/) { $ext=lc($1); } + if(-f && scalar(grep({ $ext eq lc($_);} @extensions))) { - do_display($file); + my $file=ID3FS::AudioFile->new($_); + return unless($file); + if($tag_summary) + { + gather_tags($_, $file); + } + else + { + my $changes=0; + $changes = do_deletes($file); + $changes += do_adds($file); + if($changes) + { + do_write($file); + } + else + { + do_display($file); + } + } } } @@ -177,6 +201,93 @@ sub do_display } } +sub gather_tags +{ + my($path, $file)=@_; + my @tags=$file->tags(); + @tags=map { join('/', grep { defined; } @$_); } @tags; + @tags=ID3FS::AudioFile::uniq(@tags); + $file_tags{$path}=\@tags; +} + +sub summarize_tags +{ + my @all_tags=ID3FS::AudioFile::uniq(map { @$_; } values(%file_tags)); + + # group tags by directories + my %dir_tags=(); + my @dirs=map { s/(.*)\/.*/$1/; $_; } keys %file_tags; + @dirs=ID3FS::AudioFile::uniq(@dirs); + for my $tag (@all_tags) + { + DIR: for my $dir (@dirs) + { + for my $file (keys %file_tags) + { + next unless(@{$file_tags{$file}}); + next unless($file =~ /^$dir/); + next DIR unless(grep { $_ eq $tag; } @{$file_tags{$file}}); + } + push(@{$dir_tags{$dir}}, $tag); + } + } + + # remove dir tags from files + for my $path (keys %dir_tags) + { + for my $file (keys %file_tags) + { + next unless($file =~ /^$path/); + $file_tags{$file} = [ ID3FS::AudioFile::list_remove( + $dir_tags{$path}, + $file_tags{$file}) ]; + } + } + + # find common tags + my @common_tags=(); + OUTER: for my $tag (@all_tags) + { + for my $taglist (values(%dir_tags)) + { + next OUTER unless(grep { $_ eq $tag; } @$taglist); + } + push(@common_tags, $tag); + } + + # remove common tags from %file_tags + for my $filename (keys(%file_tags)) + { + next unless(@{$file_tags{$filename}}); + $file_tags{$filename}= [ ID3FS::AudioFile::list_remove(\@common_tags, + $file_tags{$filename}) ]; + } + + # remove common tags from %dir_tags + for my $path (keys(%dir_tags)) + { + next unless(@{$dir_tags{$path}}); + $dir_tags{$path}= [ ID3FS::AudioFile::list_remove(\@common_tags, + $dir_tags{$path}) ]; + } + +# print "ALL: ", join(', ', @all_tags), "\n"; + print "Common tags: ", join(', ', @common_tags), "\n"; +# print "PER-DIR:\n"; + for my $path (sort keys %dir_tags) + { + next unless(@{$dir_tags{$path}}); + print "$path: ", join(', ', @{$dir_tags{$path}}), "\n"; + } + +# print "PER-FILE: \n"; + for my $filename (keys(%file_tags)) + { + next unless(@{$file_tags{$filename}}); + print "$filename: ", join(', ', @{$file_tags{$filename}}), "\n"; + } +} + sub usage { die("Usage: $me [-vhALSNY0CDG] [-a ARTIST] [-l ALBUM] [-s SONG] [-n TRACKNUM] FILES...\n". @@ -205,6 +316,7 @@ sub usage " -t|--add-tags|tags=TAG1,TAG2 Add tags to genre tag, merging with existing ones\n". " -T|--delete-tags=TAG1,TAG2 Delete tags from genre\n". " -r|--replace-tags TAGS1 TAGS2 Replace TAGS1 in genre with TAGS2\n". + " -V|--summary Summarize tags by directory\n" . " -v|--verbose Verbose display\n". " -h|--help This help\n". " -- End of options\n");