id3fs-tag: -V: summarize tags in directories
authorIan Beckwith <ianb@erislabs.net>
Sat, 6 Nov 2010 22:39:10 +0000 (22:39 +0000)
committerIan Beckwith <ianb@erislabs.net>
Sat, 6 Nov 2010 22:39:10 +0000 (22:39 +0000)
bin/id3fs-tag
lib/ID3FS/AudioFile.pm
lib/ID3FS/AudioFile/Mp3.pm

index 0b1f20e..6bff1c4 100755 (executable)
@@ -25,13 +25,15 @@ use vars qw($me);
 $me=($0=~/(?:.*\/)?(.*)/)[0];
 
 my @extensions=qw(mp3); # FIXME:  flac ogg
+my (%argv_tags, %dir_tags, %file_tags);
+my $current_argv;
 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(
@@ -58,6 +60,7 @@ 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);
@@ -69,9 +72,13 @@ while(my $path=shift @ARGV)
        warn("$me: $path: not found\n");
        next;
     }
+    $current_argv=$path; # ick, global nastiness
     File::Find::find( {wanted => \&wanted, follow => 1, no_chdir => 1}, $path);
 }
 
+summarize_tags() if($tag_summary);
+
+
 sub wanted
 {
     my $ext='';
@@ -80,16 +87,23 @@ sub wanted
     {
        my $file=ID3FS::AudioFile->new($_);
        return unless($file);
-       my $changes=0;
-       $changes =  do_deletes($file);
-       $changes += do_adds($file);
-       if($changes)
+       if($tag_summary)
        {
-           do_write($file);
+           gather_tags($_, $file);
        }
        else
        {
-           do_display($file);
+           my $changes=0;
+           $changes =  do_deletes($file);
+           $changes += do_adds($file);
+           if($changes)
+           {
+               do_write($file);
+           }
+           else
+           {
+               do_display($file);
+           }
        }
     }
 }
@@ -189,6 +203,49 @@ 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;
+    my @argv_tags=();
+    @argv_tags=@{$argv_tags{$current_argv}} if($argv_tags{$current_argv});
+    $argv_tags{$current_argv}=[ ID3FS::AudioFile::uniq(@tags, @argv_tags) ];
+}
+
+sub summarize_tags
+{
+    my @all_tags=ID3FS::AudioFile::uniq(map { @$_; } values(%argv_tags));
+    # find common tags
+    my @common_tags=();
+OUTER: for my $tag (@all_tags)
+    {
+       for my $taglist (values(%argv_tags))
+       {
+           next OUTER unless(grep { $_ eq $tag; } @$taglist);
+       }
+       push(@common_tags, $tag);
+    }
+    print "ALL: ",    join(', ', @all_tags), "\n";
+    print "COMMON: ", join(', ', @common_tags), "\n";
+
+    use Data::Dumper;
+    # remove common tags from %argv_tags
+    for my $argv (keys(%argv_tags))
+    {
+       next unless(@{$argv_tags{$argv}});
+       $argv_tags{$argv}= [ ID3FS::AudioFile::list_remove(\@common_tags, $argv_tags{$argv}) ];
+    }
+
+    print "PER-DIR: \n";
+    for my $argv (keys(%argv_tags))
+    {
+       print "$argv: ", join(', ', @{$argv_tags{$argv}}), "\n";
+    }
+}
+
 sub usage
 {
     die("Usage: $me [-vhALSNY0CDG] [-a ARTIST] [-l ALBUM] [-s SONG] [-n TRACKNUM] FILES...\n".
index e020b43..ffd78d6 100644 (file)
@@ -173,4 +173,27 @@ sub stripslashes
     return $text;
 }
 
+# This location for these subs is pretty much arbitrary
+sub uniq
+{
+    # class method
+    shift if(ref($_[0]) eq "ID3FS::AudioFile");
+    my (@things)=@_;
+    my %hash=();
+    @hash{@things}=();
+    return(sort keys(%hash));
+}
+
+sub list_remove
+{
+    my($remove, $list)=@_;
+    return(()) unless($list && @$list);
+    my @list=@$list;
+    for my $tag (@$remove)
+    {
+       @list=grep { $_ ne $tag; } @list;
+    }
+    return(@list);
+}
+
 1;
index 7cd15b9..8ec87ef 100644 (file)
@@ -18,6 +18,7 @@ package ID3FS::AudioFile::Mp3;
 
 use strict;
 use warnings;
+use ID3FS::AudioFile;
 use MP3::Tag;
 use MP3::Info;
 
@@ -145,7 +146,7 @@ sub add_tags
     my($self, @tags)=@_;
     my $existing=$self->tags();
     my @existing=split(/\s*,\s*/, $existing) if($existing);
-    my @merged=$self->uniq(@tags, @existing);
+    my @merged=ID3FS::AudioFile::uniq(@tags, @existing);
     my $genre=join(', ', @merged);
     return($self->set("genre", $genre));
 }
@@ -301,13 +302,6 @@ sub delete
     }
 }
 
-sub uniq
-{
-    my ($self, @things)=@_;
-    my %hash=();
-    @hash{@things}=();
-    return(sort keys(%hash));
-}
 
 sub channels
 {