X-Git-Url: https://diplodocus.org/git/flac-archive/blobdiff_plain/c069d00b1502aa08be2bdf0a197ab1110ba350d5..956d1d13564d3a830d2ec2e817d95c521857ce3d:/fa-flacd diff --git a/fa-flacd b/fa-flacd index 3e9e7cb..69566ac 100755 --- a/fa-flacd +++ b/fa-flacd @@ -21,6 +21,7 @@ use Getopt::Long qw(:config gnu_getopt no_ignore_case); use POSIX ':sys_wait_h'; use Pod::Usage; +my $debug; my $verbose; my @jobs; my @finished; @@ -37,6 +38,7 @@ sub get_tags { my $value; my $artist; my $album; + my $discnum; my @tags; verbose("Opening tags file $fn\n"); @@ -47,17 +49,43 @@ sub get_tags { ($tag, $value) = split(/=/, $_, 2); - if (/^ARTIST=/) { + if (/^ARTIST=/i) { $artist = $value; verbose("ARTIST $artist from $fn\n"); - } elsif (/^ALBUM=/) { + } elsif (/^ALBUM=/i) { $album = $value; - verbose("ALBUM $album from $fn\n"); + verbose("ALBUM $album from $fn\n"); # cperl-mode sucks " + } elsif (/^DISCNUMBER=/i) { + $discnum = int($value); + verbose("DISCNUMBER $discnum from $fn\n"); } } close(TAGS) or die("close($fn): $!"); - return ($artist, $album, @tags); + return ($artist, $album, $discnum, @tags); +} + +# Hash of Hashes of Lists Push +sub hhlp { + my $hash = shift; + my $key1 = shift; + my $key2 = shift; + my $val = shift; + + return push(@{$hash->{$key1}->{$key2}}, $val); +} + +sub bork_tags { + my $h = shift; + my @result; + + while (my ($key, $vall) = each(%$h)) { + for my $val (@$vall) { + push(@result, "$key=$val") + } + } + + return @result; } # Process the fa-rip output in the directory DIR. @@ -65,6 +93,7 @@ sub flac { my $dir = shift; my $artist; my $album; + my $discnum; my @tags; my $outfile; my $status; @@ -73,45 +102,93 @@ sub flac { rename("$dir/tags", "$dir/using-tags") or die("rename($dir/tags, $dir/using-tags): $!"); - ($artist, $album, @tags) = get_tags("$dir/using-tags"); + ($artist, $album, $discnum, @tags) = get_tags("$dir/using-tags"); + for ($artist, $album) { + s|/|_|g; + } verbose("mkdir($artist)\n"); -d $artist or mkdir($artist) or die("mkdir($artist): $!"); + my $outdir = "$artist/$album"; + verbose("mkdir($outdir)\n"); + -d "$outdir" or mkdir("$outdir") or die("mkdir($outdir): $!"); + verbose("chdir($dir)\n"); chdir($dir) or die("chdir($dir): $!"); - $outfile = "$album"; - $outfile =~ s/\//_/g; + my @artist; + my %things; + my (@bork, @titles); + for my $tag (@tags) { + if ($tag =~ /^([^[]+)\[(\d+)]=(.*)/) { + hhlp(\%things, $2, $1, $3); + } elsif ($tag =~ /^ARTIST=/) { + push(@artist, $tag); + } else { + push(@bork, $tag); + } + } + @tags = @bork; + + my @files; + for my $tracknum (sort(map(int, keys(%things)))) { + my $title = join(' ', map(split, @{$things{$tracknum}->{'TITLE'}})); + $title =~ s|/|_|g; + $outfile = join(' ', + (defined($discnum) + ? sprintf('%02d', $discnum) + : ()), + sprintf('%02d', $tracknum), + $title); + push(@files, "$outdir/$outfile.flac"); + $outfile = "../$outdir/$outfile"; + + my @lartist; + if (exists($things{$tracknum}->{'ARTIST'})) { + @lartist = (); + } else { + @lartist = @artist; + } - verbose("Running flac\n"); - $status = system('flac', '-o', "../$artist/$outfile.flac-tmp", - '--delete-input-file', '-V', '--cuesheet', - 'cue', '--no-padding', '--best', - map({ ('-T', $_) } @tags), - 'wav'); - if (WIFEXITED($status)) { - if (($status = WEXITSTATUS($status)) != 0) { - die("flac exited with status $status"); + verbose("Running flac\n"); + $status = system('flac', '-o', "$outfile.flac-tmp", + '--delete-input-file', '-V', '--no-padding', '--best', + map({ ('-T', $_) } + @lartist, + grep({ $_ !~ /^ARTIST=/ } @tags), + bork_tags($things{$tracknum})), + sprintf('track%02d.cdda.wav', $tracknum)); + if (WIFEXITED($status)) { + if (($status = WEXITSTATUS($status)) != 0) { + die("flac exited with status $status"); + } + } elsif (WIFSIGNALED($status)) { + die("flac killed with signal ", WTERMSIG($status)); + } elsif (WIFSTOPPED($status)) { + die("flac stopped with signal ", WSTOPSIG($status)); + } else { + die("Major horkage on system(flac): \$? = $? \$! = $!"); } - } elsif (WIFSIGNALED($status)) { - die("flac killed with signal ", WTERMSIG($status)); - } elsif (WIFSTOPPED($status)) { - die("flac stopped with signal ", WSTOPSIG($status)); - } else { - die("Major horkage on system(flac): \$? = $? \$! = $!"); + + rename("$outfile.flac-tmp", "$outfile.flac") + or die("rename($outfile.flac-tmp, $outfile.flac): $!"); } verbose("Cleaning up $dir\n"); unlink('using-tags') or die("unlink(using-tags): $!"); unlink('cue') or die("unlink(cue): $!"); - rename('log', "../$artist/$outfile.log") - or die("rename(log, ../$artist/$outfile.log): $!"); + rename('log', "../$outdir/log") + or die("rename(log, ../$outdir/log): $!"); chdir('..') or die("chdir(..): $!"); - rmdir($dir) or die("rmdir($dir): $!"); - rename("$artist/$outfile.flac-tmp", "$artist/$outfile.flac") - or die("rename($artist/$outfile.flac-tmp, $artist/$outfile.flac): $!"); + if (-x "$dir/post-processor") { + verbose("Running './$dir/post-processor'\n"); + system("./$dir/post-processor", @files); + unlink("$dir/post-processor") or die("unlink($dir/post-processor): $!"); + } + + rmdir($dir) or die("rmdir($dir): $!"); return 0; } @@ -130,11 +207,15 @@ sub newjob { my $dir = shift; my $pid; - $pid = fork(); - if (not defined($pid)) { - die("fork: $!"); - } elsif ($pid == 0) { - $SIG{CHLD} = 'IGNORE'; + if (not $debug) { + $pid = fork(); + if (not defined($pid)) { + die("fork: $!"); + } + } + + if ($debug or $pid == 0) { + $SIG{CHLD} = 'DEFAULT'; open(STDERR, ">$dir/log") or die("open(STDERR, >$dir/log): $!"); exit(flac($dir)); } @@ -198,6 +279,7 @@ MAIN: { $jobs = 4; GetOptions( + 'debug|X' => \$debug, 'jobs|j=i' => \$jobs, 'verbose|v' => \$verbose, 'help|h|?' => \$help, @@ -241,6 +323,17 @@ the "log" file. Finally, B moves the "cue" and "log" files to the artist directory (named by album) and removes the temporary directory. +If the temporary directory contains an executable file named +"post-processor", B executes that file with the relative +path to the output FLAC file as an argument. The output files are in +their final location when "post-processor" starts. Possible uses are +running B, moving the output files to a different location, +removing the lock file, or adding to a database. The standard input, +output, and error streams are inherited from B, so they may +be connected to anything from a tty to /dev/null. This means that you +may want to redirect these streams, if you want to save them or do any +logging. + =head1 OPTIONS =over 4