]> diplodocus.org Git - flac-archive/blob - fa-rip
Use Getopt::Long and Pod::Usage instead of Getopt::Std. As a side
[flac-archive] / fa-rip
1 #! /usr/bin/env perl
2
3 # $Id$
4 # $URL$
5
6 =head1 NAME
7
8 B<fa-rip> - rip a CD for B<fa-flacd>
9
10 =head1 SYNOPSIS
11
12 B<fa-rip> [B<-d> I<device>] [B<-t> I<track-count>]
13
14 =cut
15
16 use strict;
17 use warnings;
18
19 use Env qw(
20 CDDEV
21 );
22
23 use File::Temp;
24 use Getopt::Long;
25 use POSIX ':sys_wait_h';
26 use Pod::Usage;
27
28 use MusicBrainz::Client::Simple;
29
30 sub run_or_die {
31 my $command = shift;
32 my $status;
33
34 system($command);
35
36 if (WIFEXITED($?)) {
37 $status = WEXITSTATUS($?);
38 if ($status != 0) {
39 die("$command exited $status");
40 }
41
42 } elsif (WIFSIGNALED($?)) {
43 $status = WTERMSIG($?);
44 die("$command signalled $status");
45
46 } elsif (WIFSTOPPED($?)) {
47 $status = WSTOPSIG($?);
48 die("$command stopped $status");
49
50 } else {
51 die("Major horkage on system($command): \$? = $? \$! = $!");
52 }
53 }
54
55 sub mkcue {
56 my $device = shift;
57 my $trackcount = shift;
58 my @command;
59
60 push(@command, 'mkcue');
61
62 if (defined($trackcount)) {
63 push(@command, "-t $trackcount");
64 }
65
66 if (defined($device)) {
67 push(@command, $device);
68 }
69
70 push(@command, '> cue');
71 run_or_die(join(' ', @command));
72
73 if (not defined($trackcount)) {
74 open(F, 'cue') or die("open(cue): $!");
75 $trackcount = grep(/TRACK.*AUDIO/, <F>);
76 close(F);
77 }
78
79 return $trackcount;
80 }
81
82 sub tags {
83 my $device = shift;
84 my $trackcount = shift;
85 my $mb;
86 my @results;
87 my $album;
88 my $i;
89 my @tracks;
90 my $name;
91 my $track;
92 my $j;
93
94 if (defined($device)) {
95 $mb = new MusicBrainz::Client::Simple (device=>$device);
96 } else {
97 $mb = new MusicBrainz::Client::Simple;
98 }
99
100 @results = $mb->lookup_cd;
101 if (not $mb->success) {
102 die($mb->get_error);
103 }
104
105 open(F, '>candidate-tags-0') or die("open('>candidate-tags-0'): $!");
106 print(F "$_=\n") for ('ARTIST', 'ALBUM', 'DATE');
107 print(F "TITLE=\n") for 1 .. $trackcount;
108 close(F) or die("close('>candidate-tags-0'): $!");
109
110 for $album (@results) {
111 $i++;
112 open(F, ">candidate-tags-$i") or die("open(>candidate-tags-$i): $!");
113
114 print(F 'ARTIST=', $album->get_artist->get_name, "\n");
115 print(F 'ALBUM=', $album->get_name, "\n");
116
117 # MusicBrainz doesn't have dates yet; these are usually wrong anyway.
118 print(F "DATE=\n");
119
120 @tracks = $album->get_tracks;
121 for $j (1 .. $trackcount) {
122 if ($track = shift(@tracks)) {
123 $name = $track->get_name;
124 } else {
125 $name = '';
126 }
127 print(F "TITLE=$name\n");
128 }
129
130 close(F) or die("close(>candidate-tags-$i): $!");
131 }
132 }
133
134 sub rip {
135 my $device = shift;
136 my $trackcount = shift;
137
138 $device ||= '/dev/cdrom';
139
140 print"$_\n" for ('cdparanoia', '-d', $device, "1-$trackcount", 'wav');
141 exec('cdparanoia', '-d', $device, "1-$trackcount", 'wav');
142 # exec prints its own error message so just
143 die;
144 }
145
146 MAIN: {
147 my $trackcount;
148 my $help;
149 my $tempdir;
150
151 GetOptions(
152 'device|d=s' => \$CDDEV,
153 'tracks|t=i' => \$trackcount,
154 'help|h|?' => \$help,
155 ) or pod2usage();
156 $help and pod2usage(-exitstatus=>0, -verbose=>1);
157
158 # File::Temp::tempdir calls die on error.
159 $tempdir = File::Temp::tempdir('flac-archive.XXXXXXXXXX');
160 chdir($tempdir) or die("chdir($tempdir): $!");
161
162 $trackcount = mkcue($CDDEV, $trackcount);
163 tags($CDDEV, $trackcount);
164 rip($CDDEV, $trackcount);
165 }
166
167 \f
168 __END__
169
170 =head1 DESCRIPTION
171
172 B<fa-rip> creates a temporary directory for storage of its
173 intermediate files, runs C<mkcue(1)> to create the "cue" file, uses
174 MusicBrainz to generate candidate tags files, and runs
175 C<cdparanoia(1)> to rip the CD to the "wav" file.
176
177 In order for this CD to be processed by B<fa-flacd>, you must create a
178 "tags" file. This is usually done by renaming one of the
179 candidate-tags files and deleting the others. Don't forget to fill in
180 the DATE tag in the selected candidate before renaming it. If
181 B<fa-rip> could not find any tag information from MusicBrainz, you'll
182 have to fill out the candidate-tags-0 template.
183
184 =head1 OPTIONS
185
186 =over 4
187
188 =item B<-d> [B<--device>] I<device>
189
190 Use I<device> as the CD-ROM device, instead of the default
191 "/dev/cdrom" or the environment variable CDDEV.
192
193 =item B<-t> [B<--tracks>] I<track-count>
194
195 Archive only the first I<track-count> tracks. This is handy for
196 ignoring data tracks.
197
198 =back
199
200 =head1 ENVIRONMENT
201
202 =over 4
203
204 =item CDDEV
205
206 B<fa-rip> uses this to rip audio and save the cuesheet for a CD. It
207 makes some effort to check some common device names for FreeBSD,
208 Linux, and NetBSD by default.
209
210 =back
211
212 =head1 AUTHORS
213
214 Written by Eric Gillespie <epg@pretzelnet.org>.
215
216 flac-archive is free software; you may redistribute it and/or modify
217 it under the same terms as Perl itself.
218
219 =cut
220
221 # Local variables:
222 # cperl-indent-level: 4
223 # perl-indent-level: 4
224 # indent-tabs-mode: nil
225 # End:
226
227 # vi: set tabstop=4 expandtab: