CD ripping

Bennett Todd bet at rahul.net
Fri Jul 9 11:44:35 PDT 2004


<http://rip.sf.net/> does indeed rock, and it's got to be the
fastest way for someone who's comfortable in perl and Unix, who
likes console/cmdline apps, but who knows nothing about audio
ripping to get going. It handily embeds a wealth of trivia about how
to invoke cdparanoia/cdda2wav and lame/oggenc/gogo/bladeenc/flac,
and how to use CDDB_get to automate tagging the ripped encoded
tracks and putting them into nicely-named files.

Once I got into the swing of things, I decided I wanted things ever
so slightly different. I wanted the tracks with filenames preceeded
by tracknumbers, instead of the m3u playlist file. I wanted it to be
completely non-interactive; if freedb didn't have CDDB data for the
tracks, rip 'em into names that can later be re-named / re-tagged
but go ahead and rip 'em.

So I wrote my own rip, which I'm calling bentrip. I attach the
current version. If anybody finds it of any use, please let me know
and I'll email you if I end up doing any enhancements or bugfixes. I
_think_ it's close to feature-complete for my tastes right now, but
I've only ripped 3 CDs with it so far, so I may end up banging on it
some more.

Unlike the rip at rip.sf.net, this one doesn't know about all the
options and all the rippers and encoders; it doesn't have any
options, it has one set of options with cdparanoia and oggenc
hard-coded. It's bentrip. I'm invoking it as bentrip;eject, then
using uparrow/return after I load the next CD.

-Bennett
-------------- next part --------------
#!/usr/bin/perl -w
use strict;
use CDDB_get;

=head1 NAME

  bentrip --- Bennett's ripper

=head1 SYNOPSIS

  bentrip

	or perhaps

  while true;do
      bentrip
      eject
      echo -n "Another? "
      read ans
  done

=head1 DESCRIPTION

bentrip rips one CD into the current working subdirectory. The
ripping is hardwired, cdparanoia with default options into oggenc
--bitrate 160 (parameters, and indeed the idea and the way to do
this all shamlessly stolen from Gregory J. Smethells' rip, as found
at http://rip.sourceforge.net/). Details hardwired to Bennett's
preferences. bentrip, unlike Gregory J. Smethells' rip, is
completely and utterly non-interactive; it writes the best it can
and fills in defaults for anything it can't find out.

Aside from system permission problems and the ilke, it only bombs if
CDDB_get::get_cddb fails to produce a CDDB id and a count of tracks.

=cut

my $VERSION = "1.0";

my %cd = CDDB_get::get_cddb({
    CDDB_HOST => "freedb.freedb.org",
    CDDB_PORT => 888,
    CDDB_MODE => "http",
    input     => 0,
    HELLO_ID  => "bet\@rahul.net rip script $VERSION",
    HTTP_PROXY => ($ENV{HTTP_PROXY} or $ENV{http_proxy}),
});

die "CDDB_get did not acquire cddb id" unless defined $cd{id};
die "Unknown number of tracks" unless defined $cd{tno};
&edit(\%cd);
&burn(\%cd, "/dev/cdrom");

sub edit {
    my ($cd) = @_;
    local *_;

    my $id = $cd->{id};
    for (qw(artist title cat)) {
	$cd->{$_} = "unknown $_ $id" unless defined $cd->{$_};
    }
    for my $i (1 .. $cd->{tno}) {
	$cd->{track}[$i-1] = sprintf("track%3d", $i) unless defined $cd->{track}[$i-1];
    }
}

sub burn {
    my ($cd) = @_;
    local *_;

    my $artist = $cd->{artist}; $artist =~ y/a-zA-Z0-9_-//cds;
    $artist = $cd->{id} unless length $artist;
    -d $artist or mkdir $artist or die;
    my $title = $cd->{title}; $title =~ y/a-zA-Z0-9_-//cds;
    $title = $cd->{id} unless length $title;
    -d "$artist/$title" or mkdir "$artist/$title" or die;
    my ($year, $mon, $day) = (localtime(time))[5,4,3];
    $year += 1900; $mon++;
    my $date = sprintf("$year-%02.2d-%02.2d", $mon, $day);
    $| = 1;
    track: for my $track (1 .. $cd->{tno}) {
	print "Ripping track $track of $cd->{tno}\n";
	my $filename;
	$filename = $cd->{track}[$track-1];
	$filename =~ y/a-zA-Z0-9_-//cds;
	$filename = sprintf("$artist/$title/%03d-$filename.ogg", $track);
	if (-f $filename) {
	    print "No I am not, it is already there\n";
	    next track;
	}
	pipe READER, WRITER or die;
	my $oggpid = fork;
	die unless defined $oggpid;
	if ($oggpid == 0) {
	    close WRITER or die;
	    open STDIN, "<&", \*READER or die;
	    exec "oggenc", "-",
		"--bitrate", 160,
		"-t", $cd->{track}[$track-1],
		"-a", $cd->{artist},
		"-l", $cd->{title},
		"-N", $track,
		"-c", "genre=$cd->{cat}",
		"-c", "encode_date=$date",
		"-c", "cddb_id=$cd->{id}",
		"-o", $filename;
	    die "oggenc did not exec";
	}
	my $cdparanoiapid = fork;
	die unless defined $cdparanoiapid;
	if ($cdparanoiapid == 0) {
	    close READER or die;
	    open STDOUT, ">&", \*WRITER or die;
	    exec "cdparanoia", "-d", "/dev/cdrom", "-q", $track, "-";
	    die "cdparanoia did not exec";
	}
	close READER or die;
	close WRITER or die;
	$SIG{INT} = sub { unlink $filename; die "interrupted, cleaned up $filename" };
	my $waitpid = waitpid $oggpid, 0;
	unlink $filename and die "wacko waitpid ogg" unless $waitpid == $oggpid;
	unlink $filename and die "oggenc roached exit status $?" if $?;
	$waitpid = waitpid $cdparanoiapid, 0;
	unlink $filename and die "wacko waitpid cdparanoia" unless $waitpid == $cdparanoiapid;
	unlink $filename and die "cdparanoia roached exit status $?" if $?;
	$SIG{INT} = 'DEFAULT';
    }
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.linuxfromscratch.org/pipermail/lfs-chat/attachments/20040709/c155e704/attachment.sig>


More information about the lfs-chat mailing list