#!/usr/bin/perl use CDDB_get; use MDK::Common; my $min_free_space = 50_000; # in KiB my $dir_ = $ENV{PWD}; my $dev = '/dev/cdrom'; #$dev = '/dev/scd0'; #$dir_ = "/mnt/big/lost+found"; $| = 1; my %h = CDDB_get::get_cddb({ input => 1, CD_DEVICE => $dev }); if (!defined $h{title}) { my ($id, $total, $toc) = @{ CDDB_get::get_discids() }; $h{id} = sprintf("%08x", $id); $h{tno} = $total; $h{frames} = [ map { $_->{frames} } @$toc ]; print "Unknown disc\n"; do { print "Author? "; chomp($h{artist} = ); print "Title? "; chomp($h{title} = ); my @l; while (@l != $h{tno}) { print "File containing track names? "; chomp(my $f = ); @l = map { /^\s*(.*?)\s*$/ } cat_($f); @l > $h{tno} and print "Too many track names!\n"; @l < $h{tno} and print "Not enough track names!\n"; }; $h{track} = \@l; print "Author: \"$h{artist}\" Title: \"$h{title}\"\n"; each_index { printf "#%2d %s\n", $::i + 1, $_ } @l; print "Is it ok? (Y/n) "; } until !~ /n/; } my $dir = "$dir_/" . to_ascii($h{artist}) . "/" . to_ascii($h{title}); mkdir_p($dir); chdir($dir) or die "bad directory $dir"; log_it("working in $dir"); my $wav; # wav being ripped my (@to_encode, $encoder_pid); sub start_encoder { return if $encoder_pid || !@to_encode; $SIG{CHLD} = \&child_catch; my ($track, $wav, $ogg) = @{$to_encode[0]}; if ($encoder_pid = fork) { log_it("Encoding $ogg"); } else { exec "nice", "lame", '--vbr-new', '--ta' => $h{artist}, '--tl' => $h{title}, '--tt' => $h{track}[$track], '--quiet', $wav, $ogg or die "lame failed"; } } sub exiting { unlink $wav; log_it("cdparanoia didn't succeed, leaving"); kill 15, $encoder_pid; sleep 2; } sub child_catch { my $pid = waitpid(-1, 1); return if $pid <= 0; # print "pid $pid vs encoder_pid $encoder_pid\n"; if ($pid != $encoder_pid) { # it must be cdparanoia $? == 0 or exiting(); } $encoder_pid = 0; my ($track, $wav, $ogg) = @{$to_encode[0]}; if ($? == 0) { unlink $wav; shift @to_encode; start_encoder(); } else { unlink $ogg; log_it("lame failed on $wav"); } }; my @tracks = (1 .. $h{tno}); #@tracks = (10..17); for my $track (map { $_ - 1 } @tracks) { $wav = sprintf("%02d.wav", $track + 1); my $ogg = sprintf("%02d%s.mp3", $track + 1, to_ascii($h{track}[$track])); next if -e $ogg; if (!-e $wav) { my $free_space = ((MDK::Common::System::df($dir))[1] - $min_free_space) / (2352 / 1024); if ($h{frames}[$track + 1] - $h{frames}[$track] > $free_space) { # not enough space to rip this one log_it("No space left to go on, sleeping..."); sleep 120; # will be awaken up ASAP by SIGCHLD redo; } log_it("ripping track $track ($h{track}[$track])"); system("cdparanoia", "-d", $dev, $track + 1, $wav) == 0 or exiting(); } push @to_encode, [ $track, $wav, $ogg ]; start_encoder(); } system("eject", $dev); while (@to_encode) { log_it("Waiting for encoder to finish"); sleep 1000; } sub to_ascii { local $_ = $_[0]; tr[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ] [AAAAAAACEEEEIIIIDNOOOOOxOUUUUY_aaaaaaaceeeeiiiionooooo_ouuuuy_y]; s/ß/ss/g; tr/A-Z/a-z/; s/\s/_/g; s/\W//g; $_; } sub log_it { my ($s) = @_; print "\n* $s " . ("*" x (100 - length $s)) . "\n"; }