pastebin - collaborative debugging tool
kpaste.net RSS


replaygain
Posted by Anonymous on Thu 6th Sep 2012 21:06
raw | new post
modification of post by Anonymous (view diff)

  1. #!/usr/bin/perl
  2.  
  3. use 5.14.0;
  4. use strict;
  5. use warnings;
  6. #use File::Find qw(finddepth);
  7. use File::Copy qw(move);
  8. use File::Basename qw(basename dirname);
  9. use File::Path qw(make_path);
  10.  
  11. #my $library = "/home/sir/Music/Songbird Music";
  12. my $library = "/home/sir/Music/Songbird Music";
  13. my (%files, @files, @dirs);
  14. my $flac_version = '1.2.1';
  15.  
  16. getdirs($library);
  17.  
  18. foreach my $dn (sort(@dirs)) {
  19.                 chomp(my $ls = `ls "$dn"/*.flac 2> /dev/null | head -n 1`);
  20.                 if (-f $ls) {
  21.         #               my @stat = stat($dn);
  22.         #               my $ino = $stat[1];
  23.         #               say "$dn has $ino";
  24.                         undef %files;
  25.                         undef @files;
  26.                         getfiles($dn);
  27.                         my $fc = scalar(@files);
  28.                         if ($fc > 0) {
  29.                                 #replaygain($dn);
  30.                                 for (my $n = 0; $n < $fc; $n++) {
  31.                                         my $fn = $files[$n];
  32.                                         vendor($fn);
  33.                                         rmtag($fn, 'rating');
  34.                                         albumartist($fn, $fc);
  35.                                         track($fn);
  36.                                         totaltracks($fn, $fc);
  37.         #                               empty($fn);
  38.         #                               duplicate($fn);
  39.                                         discnum($fn, $n, $fc);
  40.                                 }
  41.                         }
  42.                 }
  43. }
  44. # Make this subroutine and the whole script so that each file name is stored in a hash and that each member contains an anonymous hash with the tags (the alltags hash).
  45. # This means it won't have to look up the tags again for the albumartist subroutine.
  46.  
  47. sub gettags {
  48.         my $fn = quotemeta(shift);
  49.         my (%alltags, @mflac);
  50.         open(OUTPUT, '-|', qq{metaflac --no-utf8-convert --show-vendor-tag --export-tags-to=- $fn}) || die "can't run metaflac: $!";
  51.         chomp(@mflac = (<OUTPUT>));
  52.         foreach (@mflac) {
  53.                 my (@tag, $tagname);
  54.                 if (/^reference/) {
  55.                         @tag = split(' ');
  56.                         $tagname = 'vendor_ref';
  57.                         $tag[1] = $tag[2];
  58.                 } else {
  59.                         @tag = split('=');
  60.                         $tagname = lc($tag[0]) or say $fn;
  61.                 }
  62.  
  63.                 if ($tag[1]) {
  64.                         push @{$alltags{$tagname}}, $tag[1];
  65.                 } else {
  66.                         push @{$alltags{$tagname}}, 'null';
  67.                 }
  68.         }
  69.         close(OUTPUT) || die "couldn't close metaflac: $!";
  70.         return %alltags;
  71. }
  72.  
  73. sub vendor {
  74.         my $fn = shift;
  75.         my $vendor_ref = $files{$fn}{vendor_ref}->[0];
  76.  
  77.         if ($vendor_ref ne $flac_version) {
  78.                 my $newfn = $fn . '.' . int(rand(10000));
  79.                 say "$fn: old encoder ($vendor_ref), re-encoding...";
  80.                 system('flac', '--silent', '-8', $fn, "--output-name=$newfn");
  81.                 if ($? == 0) {
  82.                         move($newfn, $fn) or die "Couldn't rename '$newfn': $!";
  83.                 } elsif ($? == 2) {
  84.                         say "Interrupted by user!";
  85.                         unlink($newfn) if (-f $newfn);
  86.                         exit;
  87.                 }
  88.         }
  89. }
  90.  
  91. sub getdirs {
  92.  
  93.         my $dn = shift;
  94.  
  95.         open(FIND, '-|', qq(find -L "$dn" -name "*" -type d))
  96.         or die "Can't run 'find': $!";
  97.         chomp(@dirs = (<FIND>));
  98.         close(FIND) or die "Can't close 'find': $!";
  99.         #@dirs = `find -L "$dn" -name "*" -type d -mindepth 1`;
  100. }
  101.  
  102. sub getfiles {
  103.         my $dn = shift;
  104.         opendir(my $dh, $dn) or die "Can't open directory '$dn': $!";
  105.         foreach (readdir $dh) {
  106.                 my $fn = "$dn/$_";
  107.                 if (/.flac$/ && -f $fn) {
  108.                         push(@files, $fn);
  109.                         $files{$fn} = { gettags($fn) };
  110.                 }
  111.         }
  112.         closedir $dh or die "Can't close directory '$dn': $!";
  113. }
  114.  
  115. sub replaygain {
  116.         my $dn = shift;
  117.         my %replaygain;
  118.  
  119.         #foreach ('REFERENCE_LOUDNESS', 'TRACK_GAIN', 'TRACK_PEAK', 'ALBUM_GAIN', 'ALBUM_PEAK') {
  120.         #       my $tag = 'REPLAYGAIN_' . $_;
  121.         #       system('metaflac', "--remove-tag=$tag", keys(%files));
  122.         #}
  123.  
  124.         foreach my $fn (sort(keys %files)) {
  125.                 if ($files{$fn}{replaygain_album_gain}) {
  126.                         $replaygain{$files{$fn}{replaygain_album_gain}->[0]}++;
  127.                 }
  128.         }
  129.         if (keys(%replaygain) != 1) {
  130.                 print "$dn: adding ReplayGain...";
  131.                 system('metaflac', '--add-replay-gain', keys(%files));
  132.                 say " done";
  133.         }
  134. }
  135.  
  136. sub albumartist {
  137.         my $fn = shift;
  138.         my $tracks = shift;
  139.  
  140.         if (!$files{$fn}{albumartist}) {
  141.  
  142.                 my $albumartist = $files{$fn}{artist}->[0];
  143.                 my %artist;
  144.                 my $max;
  145.                 if ($tracks == 1) { $max = $tracks } else { $max = $tracks / 2 }
  146.                 foreach my $fn (keys %files) { $artist{$files{$fn}{artist}->[0]}++ }
  147.                 if (keys(%artist) > $max) {
  148.                         $albumartist = 'Various Artists';
  149.                 }
  150.                 say "$fn: adding albumartist tag";
  151.                 system('metaflac', "--set-tag=ALBUMARTIST=$albumartist", $fn);
  152.         }
  153. }
  154.  
  155. sub empty {
  156.         my $fn = shift;
  157.         foreach my $k (keys %{$files{$fn}}) {
  158.                 foreach (@{$files{$fn}{$k}}) {
  159.                         if ($_ eq 'null') {
  160.                                 say "$fn: WARNING: empty $k tag";
  161.                         }
  162.                 }
  163.         }
  164. }
  165.  
  166. sub duplicate {
  167.         my $fn = shift;
  168.         my %exists;
  169.         foreach my $k (keys %{$files{$fn}}) {
  170.                 foreach (@{$files{$fn}{$k}}) {
  171.                         my $tag = quotemeta($k . '=' . $_);
  172.                         if ($exists{$tag}) {
  173.                                 say "$fn: WARNING: duplicate $k tag";
  174.                         } else {
  175.                                 $exists{$tag} = 1;
  176.                         }
  177.                 }
  178.         }
  179. }
  180.  
  181. sub track {
  182.         my $fn = shift;
  183.         my $track = $files{$fn}{tracknumber}->[0];
  184.         if (!$track) {
  185.                 say "$fn: doesn't have any tracknumber tag"
  186.         }
  187.         elsif ($track =~ m/^0/ && $track != 0) {
  188.                 say "$fn: fixing tracknumber tag";
  189.                 $track =~ s/^0+//;
  190.                 system('metaflac', '--remove-tag=TRACKNUMBER', "--set-tag=TRACKNUMBER=$track", $fn);
  191.         }
  192. }
  193.  
  194. sub totaltracks {
  195.         my $fn = shift;
  196.         my $tracks = shift;
  197.         if (
  198.         !$files{$fn}{totaltracks} &&
  199.         !$files{$fn}{tracktotal}
  200.         ) {
  201.                 say "$fn: adding totaltracks tag";
  202.                 system('metaflac', "--set-tag=TOTALTRACKS=$tracks", $fn);
  203.         }
  204.         elsif (
  205.         $files{$fn}{tracktotal} &&
  206.         !$files{$fn}{totaltracks}
  207.         ) {
  208.                 say "$fn: replacing tracktotal tag with totaltracks";
  209.                 system('metaflac', '--remove-tag=TRACKTOTAL', "--set-tag=TOTALTRACKS=$files{$fn}{tracktotal}->[0]", $fn);
  210.         }      
  211. }
  212.  
  213. sub discnum {
  214.         my $fn = shift;
  215.         my $n = shift;
  216.         my $fc = shift;
  217.  
  218.         my $dn = dirname($fn);
  219.         my $discnumber = $files{$fn}{discnumber}->[0];
  220.         my $album = $files{$fn}{album}->[0];
  221.         my ($match, $newfn);
  222.         my $regex = '[[:punct:]]?(cd|disc) ?[0-9]+[[:punct:]]?$';
  223.  
  224.         if ($album =~ /$regex/i) {
  225.                 $album =~ s/.?(${^MATCH}).?//;
  226.                 system('metaflac', '--remove-tag=ALBUM', $fn);
  227.                 system('metaflac', "--set-tag=ALBUM=$album", $fn);
  228.         }
  229.  
  230.         if (!$discnumber) {
  231.                 if (basename($fn) =~ /^[0-9]+-/) {
  232.                         $match = ${^MATCH};
  233.                         ${^MATCH} =~ /([0-9]+)/;
  234.                         $discnumber = eval { $1 =~ s/^0+//; };
  235.                 }
  236.                 elsif ($dn =~ /$regex/i) {
  237.                         $match = ${^MATCH};
  238.                         ${^MATCH} =~ /([0-9]+)/;
  239.                         $discnumber = eval { $1 =~ s/^0+//; };
  240.  
  241.                         $dn =~ s/ .?($match).?//;
  242.                         $newfn = "${dn}/" . "${discnumber}-" . basename($fn);
  243.                         make_path($dn) if (! -d $dn);
  244.                         move($fn, $newfn) or die "Couldn't rename '$fn': $!";
  245.                 }
  246.                 else {
  247.                         $discnumber = 1;
  248.                         $newfn = "${dn}/" . "${discnumber}-" . basename($fn);
  249.                         move($fn, $newfn) or die "Couldn't rename '$fn': $!";
  250.                 }
  251.  
  252.                 if (!$newfn) { $newfn = $fn }
  253.                 say "$newfn: adding discnumber tag";
  254.                 system('metaflac', "--set-tag=DISCNUMBER=$discnumber", $newfn);
  255.         }
  256. }
  257.  
  258. sub rmtag {
  259.         my $fn = shift;
  260.         foreach my $tag (@_) {
  261.                 if ($files{$fn}{$tag}) {
  262.                         say "$fn: removing $tag tag";
  263.                         system('metaflac', "--remove-tag=$tag", $fn);
  264.                 }
  265.         }
  266. }

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}





All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at