#! /usr/bin/env perl # $Id$ # $URL$ =head1 NAME B - rip a CD for B =head1 SYNOPSIS B [B<-d> I] [B<-t> I] =cut use strict; use warnings; use Env qw( CDDEV ); use File::Temp; use Getopt::Long qw(:config gnu_getopt no_ignore_case); use POSIX ':sys_wait_h'; use Pod::Usage; use MusicBrainz::Client::Simple; sub run_or_die { my $command = shift; my $status; $status = system($command); if (WIFEXITED($status)) { if (($status = WEXITSTATUS($status)) != 0) { die("$command exited with status $status"); } } elsif (WIFSIGNALED($status)) { die("$command killed with signal ", WTERMSIG($status)); } elsif (WIFSTOPPED($status)) { die("$command stopped with signal ", WSTOPSIG($status)); } else { die("Major horkage on system($command): \$? = $? \$! = $!"); } } sub mkcue { my $device = shift; my $trackcount = shift; my @command; push(@command, 'mkcue'); if (defined($trackcount)) { push(@command, "-t $trackcount"); } if (defined($device)) { push(@command, $device); } push(@command, '> cue'); run_or_die(join(' ', @command)); if (not defined($trackcount)) { open(F, 'cue') or die("open(cue): $!"); $trackcount = grep(/TRACK.*AUDIO/, ); close(F); } return $trackcount; } sub tags { my $device = shift; my $trackcount = shift; my $mb; my @results; my $album; my $i; my @tracks; my $name; my $track; my $j; if (defined($device)) { $mb = new MusicBrainz::Client::Simple (device=>$device); } else { $mb = new MusicBrainz::Client::Simple; } @results = $mb->lookup_cd; if (not $mb->success) { die($mb->get_error); } open(F, '>candidate-tags-0') or die("open('>candidate-tags-0'): $!"); print(F "$_=\n") for ('ARTIST', 'ALBUM', 'DATE'); print(F "TITLE=\n") for 1 .. $trackcount; close(F) or die("close('>candidate-tags-0'): $!"); for $album (@results) { $i++; open(F, ">candidate-tags-$i") or die("open(>candidate-tags-$i): $!"); print(F 'ARTIST=', $album->get_artist->get_name, "\n"); print(F 'ALBUM=', $album->get_name, "\n"); # MusicBrainz doesn't have dates yet; these are usually wrong anyway. print(F "DATE=\n"); @tracks = $album->get_tracks; for $j (1 .. $trackcount) { if ($track = shift(@tracks)) { $name = $track->get_name; } else { $name = ''; } print(F "TITLE=$name\n"); } close(F) or die("close(>candidate-tags-$i): $!"); } } sub rip { my $device = shift; my $trackcount = shift; $device ||= '/dev/cdrom'; exec('cdparanoia', '-d', $device, "1-$trackcount", 'wav'); # exec prints its own error message so just die; } MAIN: { my $trackcount; my $help; my $tempdir; GetOptions( 'device|d=s' => \$CDDEV, 'tracks|t=i' => \$trackcount, 'help|h|?' => \$help, ) or pod2usage(); $help and pod2usage(-exitstatus=>0, -verbose=>1); # File::Temp::tempdir calls die on error. $tempdir = File::Temp::tempdir('flac-archive.XXXXXXXXXX'); chdir($tempdir) or die("chdir($tempdir): $!"); $trackcount = mkcue($CDDEV, $trackcount); tags($CDDEV, $trackcount); rip($CDDEV, $trackcount); } __END__ =head1 DESCRIPTION B creates a temporary directory for storage of its intermediate files, runs C to create the "cue" file, uses MusicBrainz to generate candidate tags files, and runs C to rip the CD to the "wav" file. In order for this CD to be processed by B, you must create a "tags" file. This is usually done by renaming one of the candidate-tags files and deleting the others. Don't forget to fill in the DATE tag in the selected candidate before renaming it. If B could not find any tag information from MusicBrainz, you'll have to fill out the candidate-tags-0 template. =head1 OPTIONS =over 4 =item B<-d> [B<--device>] I Use I as the CD-ROM device, instead of the default "/dev/cdrom" or the environment variable CDDEV. =item B<-t> [B<--tracks>] I Archive only the first I tracks. This is handy for ignoring data tracks. =back =head1 ENVIRONMENT =over 4 =item CDDEV B uses this to rip audio and save the cuesheet for a CD. It makes some effort to check some common device names for FreeBSD, Linux, and NetBSD by default. =back =head1 AUTHORS Written by Eric Gillespie . flac-archive is free software; you may redistribute it and/or modify it under the same terms as Perl itself. =cut # Local variables: # cperl-indent-level: 4 # perl-indent-level: 4 # indent-tabs-mode: nil # End: # vi: set tabstop=4 expandtab: