]>
diplodocus.org Git - flac-archive/blob - fa-flacd
8 B<fa-flacd> - archive CDs to single FLAC files
12 B<fa-flacd> [B<-j> I<jobs>] [B<-v>]
20 use Getopt
::Long
qw(:config gnu_getopt no_ignore_case);
21 use POSIX
':sys_wait_h';
30 $verbose and print(STDERR
$_) for @_;
33 # Return the ARTIST, ALBUM, and DATE followed by a list of all the
34 # lines in the file FN.
44 verbose
("Opening tags file $fn\n");
45 open(TAGS
, $fn) or die("open($fn): $!");
50 ($tag, $value) = split(/=/, $_, 2);
54 verbose
("ARTIST $artist from $fn\n");
55 } elsif (/^ALBUM=/i) {
57 verbose
("ALBUM $album from $fn\n"); # cperl-mode sucks "
58 } elsif (/^DISCNUMBER=/i) {
59 $discnum = int($value);
60 verbose
("DISCNUMBER $discnum from $fn\n");
63 close(TAGS
) or die("close($fn): $!");
65 return ($artist, $album, $discnum, @tags);
68 # Process the fa-rip output in the directory DIR.
78 verbose
("Renaming $dir/tags\n");
79 rename("$dir/tags", "$dir/using-tags")
80 or die("rename($dir/tags, $dir/using-tags): $!");
82 ($artist, $album, $discnum, @tags) = get_tags
("$dir/using-tags");
84 verbose
("mkdir($artist)\n");
85 -d
$artist or mkdir($artist) or die("mkdir($artist): $!");
87 verbose
("chdir($dir)\n");
88 chdir($dir) or die("chdir($dir): $!");
91 defined($discnum) and $outfile .= " (disc $discnum)";
94 verbose
("Running flac\n");
95 $status = system('flac', '-o', "../$artist/$outfile.flac-tmp",
96 '--delete-input-file', '-V', '--cuesheet',
97 'cue', '--no-padding', '--best',
98 map({ ('-T', $_) } @tags),
100 if (WIFEXITED
($status)) {
101 if (($status = WEXITSTATUS
($status)) != 0) {
102 die("flac exited with status $status");
104 } elsif (WIFSIGNALED
($status)) {
105 die("flac killed with signal ", WTERMSIG
($status));
106 } elsif (WIFSTOPPED
($status)) {
107 die("flac stopped with signal ", WSTOPSIG
($status));
109 die("Major horkage on system(flac): \$? = $? \$! = $!");
112 verbose
("Cleaning up $dir\n");
113 unlink('using-tags') or die("unlink(using-tags): $!");
114 unlink('cue') or die("unlink(cue): $!");
115 rename('log', "../$artist/$outfile.log")
116 or die("rename(log, ../$artist/$outfile.log): $!");
117 chdir('..') or die("chdir(..): $!");
119 rename("$artist/$outfile.flac-tmp", "$artist/$outfile.flac")
120 or die("rename($artist/$outfile.flac-tmp, $artist/$outfile.flac): $!");
122 if (-x
"$dir/post-processor") {
123 verbose
("Running './$dir/post-processor $artist/$outfile.flac'\n");
124 system("./$dir/post-processor", "$artist/$outfile.flac");
125 unlink("$dir/post-processor") or die("unlink($dir/post-processor): $!");
128 rmdir($dir) or die("rmdir($dir): $!");
136 while (($pid = waitpid(-1, WNOHANG
)) > 0) {
137 push(@finished, [$pid, $?]);
140 $SIG{CHLD
} = \
&reaper
;
149 if (not defined($pid)) {
154 if ($debug or $pid == 0) {
155 $SIG{CHLD
} = 'IGNORE';
156 open(STDERR
, ">$dir/log") or die("open(STDERR, >$dir/log): $!");
160 verbose
("new job $pid for $dir\n");
170 $pid = $finished[$i][0];
171 $status = $finished[$i][1];
173 verbose
("$pid finished (");
174 if (WIFEXITED
($status)) {
175 verbose
('exited with status ', WEXITSTATUS
($status));
176 } elsif (WIFSIGNALED
($status)) {
177 verbose
('killed with signal ', WTERMSIG
($status));
178 } elsif (WIFSTOPPED
($status)) {
179 verbose
('stopped with signal ', WSTOPSIG
($status));
183 for ($j = 0; $j <= $#jobs; $j++) {
184 $pid == $jobs[$j] and splice(@jobs, $j, 1) and last;
187 splice(@finished, $i, 1);
196 $SIG{CHLD
} = \
&reaper
;
198 if (scalar(@jobs) <= $MAXJOBS) {
199 foreach $i (glob('*/tags')) {
200 push(@jobs, newjob
(dirname
($i))) <= $MAXJOBS or last;
204 for ($i = 0; $i <= $#finished; $i++) {
208 verbose
(scalar(@jobs), " jobs\n");
219 'debug|X' => \
$debug,
220 'jobs|j=i' => \
$jobs,
221 'verbose|v' => \
$verbose,
222 'help|h|?' => \
$help,
224 $help and pod2usage
(-exitstatus
=>0, -verbose
=>1);
234 B<fa-flacd> and B<fa-rip> together comprise B<flac-archive>, a system
235 for archiving audio CDs to single FLAC files. B<fa-flacd> is the guts
236 of the system. It runs in the directory where the audio archives are
237 stored, scanning for new ripped CDs to encode and rename; it never
238 exits. B<fa-rip> generates the inputs for B<fa-flacd>: the ripped WAV
239 file, Vorbis tags, and a cuesheet.
241 Both programs expect to be run from the same directory. They use that
242 directory to manage directories named by artist. Intermediate files
243 are written to temporary directories here. B<fa-flacd> processes the
244 temporary directories into per-album files in the artist directories.
246 Every 5 seconds, B<fa-flacd> scans its current directory for
247 directories with a file called "tags" and creates a processing job for
248 each one. The number of jobs B<fa-flacd> attempts to run is
249 controlled by the B<-j> option and defaults to 4. B<fa-flacd> will
250 print diagnostic output when the B<-v> option is given.
252 A processing job first renames the directory's "tags" file to
253 "using-tags" so that B<ra-flacd> will not try to start another job for
254 this directory. This file is left as is when an error is encountered,
255 so a new job will not be started until the user corrects the error
256 condition and renames "using-tags" back to "tags". Next, it encodes
257 the "wav" file to a FLAC file, using the "cue" file for the cuesheet
258 and "using-tags" for Vorbis tags. Any diagnostic output is saved in
259 the "log" file. Finally, B<fa-flacd> moves the "cue" and "log" files
260 to the artist directory (named by album) and removes the temporary
263 If the temporary directory contains an executable file named
264 "post-processor", B<fa-flacd> executes that file with the relative
265 path to the output FLAC file as an argument. The output files are in
266 their final location when "post-processor" starts. Possible uses are
267 running B<flac2mp3>, moving the output files to a different location,
268 removing the lock file, or adding to a database. The standard input,
269 output, and error streams are inherited from B<fa-flacd>, so they may
270 be connected to anything from a tty to /dev/null. This means that you
271 may want to redirect these streams, if you want to save them or do any
278 =item B<-j> [B<--jobs>] I<jobs>
280 Run up to I<jobs> jobs instead of the default 4.
282 =item B<-v> [B<--verbose>]
284 Print diagnostic information.
290 Written by Eric Gillespie <epg@pretzelnet.org>.
292 flac-archive is free software; you may redistribute it and/or modify
293 it under the same terms as Perl itself.
298 # cperl-indent-level: 4
299 # perl-indent-level: 4
300 # indent-tabs-mode: nil
303 # vi: set tabstop=4 expandtab: