pastebin - collaborative debugging tool
kpaste.net RSS


replaygain
Posted by Anonymous on Wed 5th Sep 2012 10:09
raw | new post
view followups (newest first): replaygain by Anonymous

  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.  
  15. getdirs($library);
  16.  
  17. foreach my $dn (@dirs) {
  18.                 chomp(my $ls = `ls "$dn"/*.flac 2>- | head -n 1`);
  19.                 if (-f $ls) {
  20.         #               my @stat = stat($dn);
  21.         #               my $ino = $stat[1];
  22.         #               say "$dn has $ino";
  23.                         undef %files;
  24.                         undef @files;
  25.                         getfiles($dn);
  26.                         my $fc = scalar(@files);
  27.                         if ($fc > 0) {
  28.                                 replaygain($dn);
  29.                                 for (my $n = 0; $n < $fc; $n++) {
  30.                                         #say $files[$n];
  31.                                         my $fn = $files[$n];
  32.  
  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 --export-tags-to=- $fn}) || die "can't run metaflac: $!";
  51.         chomp(@mflac = (<OUTPUT>));
  52.         foreach (@mflac) {
  53.                 my @tag = split('=');
  54.                 my $tagname = lc($tag[0]) or say $fn;
  55.                 if ($tag[1]) {
  56.                         push @{$alltags{$tagname}}, $tag[1];
  57.                 } else {
  58.                         push @{$alltags{$tagname}}, 'null';
  59.                 }
  60.         }
  61.         close(OUTPUT) || die "couldn't close metaflac: $!";
  62.         return %alltags;
  63. }
  64.  
  65. sub getdirs {
  66.  
  67.         my $dn = shift;
  68.  
  69.         open(FIND, '-|', qq(find -L "$dn" -name "*" -type d))
  70.         or die "Can't run 'find': $!";
  71.         chomp(@dirs = (<FIND>));
  72.         close(FIND) or die "Can't close 'find': $!";
  73.         #@dirs = `find -L "$dn" -name "*" -type d -mindepth 1`;
  74. }
  75.  
  76. sub getfiles {
  77.         my $dn = shift;
  78.         opendir(my $dh, $dn) or die "Can't open directory '$dn': $!";
  79.         foreach (readdir $dh) {
  80.                 my $fn = "$dn/$_";
  81.                 if (/.flac$/ && -f $fn) {
  82.                         push(@files, $fn);
  83.                         $files{$fn} = { gettags($fn) };
  84.                 }
  85.         }
  86.         closedir $dh or die "Can't close directory '$dn': $!";
  87. }
  88.  
  89. sub replaygain {
  90.         my $dn = shift;
  91.         my %replaygain;
  92.  
  93.         #foreach ('REFERENCE_LOUDNESS', 'TRACK_GAIN', 'TRACK_PEAK', 'ALBUM_GAIN', 'ALBUM_PEAK') {
  94.         #       my $tag = 'REPLAYGAIN_' . $_;
  95.         #       system('metaflac', "--remove-tag=$tag", keys(%files));
  96.         #}
  97.  
  98.         foreach my $fn (sort(keys %files)) {
  99.                 if ($files{$fn}{replaygain_album_gain}) {
  100.                         $replaygain{$files{$fn}{replaygain_album_gain}->[0]}++;
  101.                 }
  102.         }
  103.         if (keys(%replaygain) != 1) {
  104.                 print "$dn: adding ReplayGain...";
  105.                 system('metaflac', '--add-replay-gain', keys(%files));
  106.                 say " done";
  107.         }
  108. }
  109.  
  110. sub albumartist {
  111.         my $fn = shift;
  112.         my $tracks = shift;
  113.  
  114.         if (!$files{$fn}{albumartist}) {
  115.  
  116.                 my $albumartist = $files{$fn}{artist}->[0];
  117.                 my %artist;
  118.                 my $max;
  119.                 if ($tracks == 1) { $max = $tracks } else { $max = $tracks / 2 }
  120.                 foreach my $fn (keys %files) { $artist{$files{$fn}{artist}->[0]}++ }
  121.                 if (keys(%artist) > $max) {
  122.                         $albumartist = 'Various Artists';
  123.                 }
  124.                 say "$fn: adding albumartist tag";
  125.                 system('metaflac', "--set-tag=ALBUMARTIST=$albumartist", $fn);
  126.         }
  127. }
  128.  
  129. sub empty {
  130.         my $fn = shift;
  131.         foreach my $k (keys %{$files{$fn}}) {
  132.                 foreach (@{$files{$fn}{$k}}) {
  133.                         if ($_ eq 'null') {
  134.                                 say "$fn: WARNING: empty $k tag";
  135.                         }
  136.                 }
  137.         }
  138. }
  139.  
  140. sub duplicate {
  141.         my $fn = shift;
  142.         my %exists;
  143.         foreach my $k (keys %{$files{$fn}}) {
  144.                 foreach (@{$files{$fn}{$k}}) {
  145.                         my $tag = quotemeta($k . '=' . $_);
  146.                         if ($exists{$tag}) {
  147.                                 say "$fn: WARNING: duplicate $k tag";
  148.                         } else {
  149.                                 $exists{$tag} = 1;
  150.                         }
  151.                 }
  152.         }
  153. }
  154.  
  155. sub track {
  156.         my $fn = shift;
  157.         my $track = $files{$fn}{tracknumber}->[0];
  158.         if (!$track) {
  159.                 say "$fn: doesn't have any tracknumber tag"
  160.         }
  161.         elsif ($track =~ m/^0/ && $track != 0) {
  162.                 say "$fn: fixing tracknumber tag";
  163.                 $track =~ s/^0+//;
  164.                 system('metaflac', '--remove-tag=TRACKNUMBER', "--set-tag=TRACKNUMBER=$track", $fn);
  165.         }
  166. }
  167.  
  168. sub totaltracks {
  169.         my $fn = shift;
  170.         my $tracks = shift;
  171.         if (
  172.         !$files{$fn}{totaltracks} &&
  173.         !$files{$fn}{tracktotal}
  174.         ) {
  175.                 say "$fn: adding totaltracks tag";
  176.                 system('metaflac', "--set-tag=TOTALTRACKS=$tracks", $fn);
  177.         }
  178.         elsif (
  179.         $files{$fn}{tracktotal} &&
  180.         !$files{$fn}{totaltracks}
  181.         ) {
  182.                 say "$fn: replacing tracktotal tag with totaltracks";
  183.                 system('metaflac', '--remove-tag=TRACKTOTAL', "--set-tag=TOTALTRACKS=$files{$fn}{tracktotal}->[0]", $fn);
  184.         }      
  185. }
  186.  
  187. sub discnum {
  188.         my $fn = shift;
  189.         my $n = shift;
  190.         my $fc = shift;
  191.  
  192.         my $dn = dirname($fn);
  193.         my $discnumber = $files{$fn}{discnumber}->[0];
  194.         my $album = $files{$fn}{album}->[0];
  195.         my ($match, $newfn);
  196.         my $regex = '[[:punct:]]?(cd|disc) ?[0-9]+[[:punct:]]?$' ;
  197.  
  198.         if ($album =~ /$regex/i) {
  199.                 $album =~ s/.?${^MATCH}.?//;
  200.                 system('metaflac', '--remove-tag=ALBUM', $fn);
  201.                 system('metaflac', "--set-tag=ALBUM=$album", $fn);
  202.         }
  203.  
  204.         if (!$discnumber) {
  205.                 if (basename($fn) =~ /^[0-9]+-/) {
  206.                         $match = ${^MATCH};
  207.                         ${^MATCH} =~ /([0-9]+)/;
  208.                         $discnumber = $1;
  209.                         $discnumber =~ s/^0+//;
  210.                 }
  211.                 elsif ($dn =~ /$regex/i) {
  212.                         $match = ${^MATCH};
  213.                         ${^MATCH} =~ /([0-9]+)/;
  214.                         $discnumber = $1;
  215.                         $discnumber =~ s/^0+//;
  216.  
  217.                         $dn =~ s/ .?($match).?//;
  218.                         $newfn = "${dn}/" . "${discnumber}-" . basename($fn);
  219.                         make_path($dn) if (! -d $dn);
  220.                         move($fn, $newfn) or die "Couldn't rename '$fn': $!";
  221.                 }
  222.                 else {
  223.                         $discnumber = 1;
  224.                         $newfn = "${dn}/" . "${discnumber}-" . basename($fn);
  225.                         move($fn, $newfn) or die "Couldn't rename '$fn': $!";
  226.                 }
  227.  
  228.                 if (!$newfn) { $newfn = $fn }
  229.                 say "$newfn: adding discnumber tag";
  230.                 system('metaflac', "--set-tag=DISCNUMBER=$discnumber", $newfn);
  231.         }
  232. }
  233.  
  234. sub rmtag {
  235.         my $fn = shift;
  236.         foreach my $tag (@_) {
  237.                 if ($files{$fn}{$tag}) {
  238.                         say "$fn: removing $tag tag";
  239.                         system('metaflac', "--remove-tag=$tag", $fn);
  240.                 }
  241.         }
  242. }

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