grabcd-0009/0000755000175000017500000000000011126216345011661 5ustar mitchmitchgrabcd-0009/grabcd-scan0000755000175000017500000000676211126216345013766 0ustar mitchmitch#!/usr/bin/perl -w # # grabcd-scan -- create track list to an audio CD # # 2004-2006,2008 (c) by Christian Garbs # Licensed under GNU GPL # use strict; use Audio::CD; use Grabcd::ReadConfig; # globals my $VERSION = '0009'; my ($keep_year, $keep_artist, $keep_title, $keep_version) = ( 1, 1, 0, 0 ); my $config = Grabcd::ReadConfig::read_config('grabcd', qw( CDINFO_TEMP CDINFO_REMOTE )); my $file = $config->{CDINFO_TEMP}; my $remote = $config->{CDINFO_REMOTE}; my $args = join '', @ARGV; $args =~ tr/A-Z/a-z/; while ( $args =~ /(.)/g ) { if ($1 eq "y") { $keep_year = 1 - $keep_year; } elsif ($1 eq "a") { $keep_artist = 1 - $keep_artist; } elsif ($1 eq "t") { $keep_title = 1 - $keep_title; } elsif ($1 eq "v") { $keep_version = 1 - $keep_version; } else { print "a artist (keep = $keep_artist)\n"; print "t title (keep = $keep_title)\n"; print "v version (keep = $keep_version)\n"; print "y year (keep = $keep_year)\n"; exit; } } my $cd = Audio::CD->init; die "could not initialize Audio::CD\n" unless defined $cd; my $stat = $cd->close; $stat = $cd->stat; die "no cd detected\n" unless $stat->present; my $cddb = $cd->cddb; my $discid = $cddb->discid; my @tracks = @{$stat->tracks}; print "discid=[$discid], track_count=[".$stat->total_tracks."]\n"; use Term::ReadLine; my ($artist, $album, $path, $title, $version, $year, $catalog); my $term = new Term::ReadLine 'grabcd-scan '.$VERSION; $|++; $catalog = $term->readline("Catalog :"); $catalog =~ s/^\s+//; $catalog =~ s/\s+$//; $artist = $term->readline("Artist :"); $artist =~ s/^\s+//; $artist =~ s/\s+$//; $album = $term->readline("Album :"); $album =~ s/^\s+//; $album =~ s/\s+$//; open CDINFO, '>', $file or die "can't open `$file': $!\n"; print CDINFO "DISCID=$discid\n"; print CDINFO "CATALOG=$catalog\n"; print CDINFO "ALBUM=$album\n"; # read path if ($artist eq '') { $path = $album; } else { $path = $artist; $path =~ tr,/,_,; $album =~ tr,/,_,; $path .= '/' . $album; } $path = $term->readline("Path :", $path); $path =~ s/^\s+//; $path =~ s/\s+$//; print CDINFO "PATH=$path\n"; # { foreach my $track (1 .. $stat->total_tracks) { unless ($tracks[$track-1]->is_audio) { print "\nskipping $track, no audio...\n"; next; } print CDINFO "\nTRACK=$track\n"; my ($minutes, $seconds) = $tracks[$track-1]->length; printf "\n == Track %02d/%02d %02d:%02d ==\n", $track, $stat->total_tracks, $minutes, $seconds; if ($keep_artist) { $artist = $term->readline("Artist :", $artist); } else { $artist = $term->readline("Artist :"); } if ($keep_title) { $title = $term->readline("Title :", $title); } else { $title = $term->readline("Title :"); } if ($keep_version) { $version = $term->readline("Version :", $version); } else { $version = $term->readline("Version :"); } if ($keep_year) { $year = $term->readline("Year :", $year); } else { $year = $term->readline("Year :"); } $artist =~ s/^\s+//; $artist =~ s/\s+$//; $title =~ s/^\s+//; $title =~ s/\s+$//; $version=~ s/^\s+//; $version=~ s/\s+$//; $year =~ s/^\s+//; $year =~ s/\s+$//; print CDINFO "ARTIST=$artist\nTITLE=$title\nVERSION=$version\nYEAR=$year\n"; } close CDINFO or die "can't close `$file': $!\n"; system($ENV{EDITOR}, $file); $path =~ s,/,___,g; if ($remote !~ m:^/:) { # remote operation $path =~ s/([;"\\' &<>()])/\\$1/g; } system('scp', $file, "$remote/$path"); grabcd-0009/HISTORY0000644000175000017500000000155011126216345012746 0ustar mitchmitchgrabcd HISTORY == 0009 / 2008-12-29 * bugfix: change script names look out! - encode.pl is now called grabcd-encode - grabcd.pl is now called grabcd-rip - scancd.pl is now called grabcd-scan == 0008 / 2008-11-22 * less verbose output * implement sane build system == 0007 / 2008-08-05 * grabcd-rip: use icedax instead of cdparanoia * grabcd-scan: fix escaped spaces in scancd on local operation * grabcd-scan: fix missing escape for double quotes * document Audio::CD limitation of always using /dev/cdrom == 0006 / 2006-02-28 * grabcd-scan: fix storage of cdinfo file in local operation again (seldom used feature -_-;;) == 0005 / 2005-09-13 * grabcd-scan: fix storage of cdinfo file in local operation == 0004 / 2005-09-11 * grabcd-scan: don't use hardcoded jmacs but $EDITOR to edit the cdinfo file == 0003 / 2005-09-11 * Initial version. grabcd-0009/grabcd-encode0000755000175000017500000000340711126216345014270 0ustar mitchmitch#!/usr/bin/perl -w # # grabcd-encode -- encode and tag audio files # # 2004-2005,2008 (c) by Christian Garbs # Licensed under GNU GPL # use strict; use File::Path; use POSIX qw(nice); use Grabcd::ReadConfig; # globals my $VERSION = '0009'; my $config = Grabcd::ReadConfig::read_config('grabcd', qw(CDINFO_TEMP ENCODE_NICE ENCODE_PATH)); my $file = $config->{CDINFO_TEMP}; # subs sub readTag($) { my $tag = shift; while (my $line = ) { chomp $line; if ($line =~ /^\s*$tag\s*=(.*)$/i) { return $1; } } return ''; } # main nice $config->{ENCODE_NICE}; open CDINFO, '<', $file or die "can't open `$file': $!\n"; my $catalog = readTag('CATALOG'); my $album = readTag('ALBUM'); my $path = readTag('PATH'); my $first = lc(substr($path, 0, 1)); if ($first =~ /[a-z]/) { $path = "/$first/$path"; } else { $path = "/1/$path"; } $path = $config->{ENCODE_PATH} . $path; my $track_want = shift; die "no track given!" unless defined $track_want; # cycle tracks while ((my $track = readTag('TRACK')) ne '') { if ($track == $track_want) { mkpath($path); my ($artist, $title, $version, $year) = ( readTag('ARTIST'), readTag('TITLE'), readTag('VERSION'), readTag('YEAR') ); my $filename = sprintf '%02d.%s.%s.%s.ogg', $track, $artist, $title, $version; $filename =~ tr,/, ,; my @args = ('oggenc', '-Q', '-q', '6', '-N', $track, '-l', $album, '-t', $title, '-d', $year, '-a', $artist, '-o', "$path/$filename"); if ($version ne '') { push @args, ('-c', "comment=($version)"); } if ($catalog ne '') { push @args, ('-c', "catalog=$catalog"); } push @args, '-'; system( @args ); } } close CDINFO or die "can't close `$file': $!\n"; grabcd-0009/Grabcd/0000755000175000017500000000000011126216345013043 5ustar mitchmitchgrabcd-0009/Grabcd/ReadConfig.pm0000644000175000017500000000244711126216345015411 0ustar mitchmitch#!/usr/bin/perl -w # # 2005 (c) by Christian Garbs # utility function to read a simple config file # if not all keywords are found, an error is raised # $filename is searched for as "~/.$filename" and "/etc/$filename.conf" # file format is: # # comment # KEY=value use strict; package Grabcd::ReadConfig; sub read_config($@) # $_[0] = Configuration file name # $_[1..n] = must-have configuration keys # result is a hash of the configuration { my $filename = shift; my @keys = @_; my $result = {}; my $file = "$ENV{HOME}/.$filename"; if (! -r $file) { $file = "/etc/$filename.conf"; } die "ERROR: configuration file <$file> does not exist.\n" unless -e $file; die "ERROR: configuration file <$file> is not readable.\n" unless -r _; open CONF, '<', $file or die "can't open <$file>: $!\n"; while (my $line = ) { chomp $line; next if $line =~ /^\s*#/; next if $line =~ /^\s*$/; if ($line =~ /^\s*([A-Z_+-]+)=(.+)\s*$/) { $result->{uc $1} = $2; } else { warn "unparseable line $. in configuration file\n"; } } close CONF or die "can't close <$file>: $!\n"; foreach my $key (@keys) { $key = uc $key; die "ERROR: configuration option $key is not set.\n" unless exists $result->{$key}; } return $result; } 1; grabcd-0009/grabcd-rip0000755000175000017500000000437711126216345013634 0ustar mitchmitch#!/usr/bin/perl -w # # grabcd-rip -- read an audio CD and start encoding # # 2004-2005,2008 (c) by Christian Garbs # Licensed under GNU GPL # use strict; use Audio::CD; use Grabcd::ReadConfig; # globals my $VERSION = '0009'; my $config = Grabcd::ReadConfig::read_config('grabcd', qw(CDINFO_TEMP ENCODE_HOST ENCODE_BINARY)); ### vvv-- warn about old config file entry and fix it if ($config->{'ENCODE_BINARY'} =~ /encode\.pl$/) { warn <<"EOF"; _ | | Your grabcd configuration contains the script name 'encode.pl' | | in the variable ENCODE_BINARY. As of version 0009, the script | | was renamed to 'grabcd-encode'. grabcd-rip will automatically |_| try to use the new script name -- but this may fail. _ (_) Please update your configuration file to suppress this warning. EOF ; $config->{'ENCODE_BINARY'} =~ s/encode\.pl$/grabcd-encode/; } ### ^^^-- warn about old config file entry and fix it my $file = $config->{CDINFO_TEMP}; my $host = $config->{ENCODE_HOST}; my $encode = $config->{ENCODE_BINARY}; # subs sub readTag($) { my $tag = shift; while (my $line = ) { chomp $line; if ($line =~ /^\s*$tag\s*=(.*)$/i) { return $1; } } return ''; } # main my $cd = Audio::CD->init; die "could not initialize Audio::CD\n" unless defined $cd; my $stat = $cd->close; $stat = $cd->stat; die "no cd detected\n" unless $stat->present; open CDINFO, '<', $file or die "can't open `$file': $!\ndid you run grabcd-scan before?\n"; # check discid my $cddb = $cd->cddb; my $discid_want = $cddb->discid; my $discid_have = readTag('DISCID'); die "discid does not match (want=$discid_want, have=$discid_have)\ndid you run grabcd-scan before?\n" unless $discid_want eq $discid_have; # display album print 'Album : '.readTag('ALBUM' )."\n"; # copy cdinfo if ($host ne 'localhost' and $host ne '') { system("scp $file $host:$file"); } # cycle tracks while ((my $track = readTag('TRACK')) ne '') { print "\n\t*** grabbing track $track ***\n\n"; if ($host ne 'localhost' and $host ne '') { system("icedax -q -O wav -t $track -paranoia - | ssh $host $encode $track"); } else { system("icedax -q -O wav -t $track -paranoia - | $encode $track"); } } close CDINFO or die "can't close `$file': $!\n"; grabcd-0009/README0000644000175000017500000000437011126216345012545 0ustar mitchmitchgrabcd README grabcd is an audio CD ripping and encoding suite (c) 2004-2008 by Christian Garbs licensed under GNU GPL == What does it do? "grabcd-scan" reads a CD and lets you enter track information (I'm no fan of CDDB as the data there is very limited - think of a hit sampler CD with different artists, you can't have a different artist per track). "grabcd-rip" will then read the CD using icedax and start the encoding via "grabcd-encode" (this will be done automatically). You will get OGG encoded files in a specified directory hierarchy. == What's special about this? grabcd-rip and grabcd-encode can run on different machines. This was essential for me when writing these scripts as my CD-ROM was in my slow workstation while the server with the fast CPU had no CD-ROM. == How to use it? Generate a config file, either /etc/grabcd.conf for everyone or ~/.grabcd for yourself. This is an example for "everything local": CDINFO_TEMP=/tmp/cdinfo CDINFO_REMOTE=/mnt/storage/grabcd-scan ENCODE_HOST=localhost ENCODE_BINARY=/usr/bin/grabcd-encode ENCODE_NICE=20 ENCODE_PATH=/mnt/storage/ogg This is an example for "networked operation": CDINFO_TEMP=/tmp/cdinfo CDINFO_REMOTE=mitch@yggdrasil.mitch.h.shuttle.de:/home/mitch/ogg/grabcd-scan ENCODE_HOST=mitch@yggdrasil.mitch.h.shuttle.de ENCODE_BINARY=/home/mitch/bin/grabcd-encode ENCODE_NICE=20 ENCODE_PATH=/home/mitch/ogg == Configuration options CDINFO_TEMP - The artist/track data is temporarily stored here CDINFO_REMOTE - The artist/track data is archived here. Useful if you want to reread a CD later. Just copy the appropriate file to $CDINFO_TEMP and start grabcd-rip. ENCODE_HOST - Where to run grabcd-encode. Set to empty or "localhost" for local operation. Set to a "hostname" or "user@hostname" for remote operation. ENCODE_BINARY - Where to find the grabcd-encode binary. ENCODE_NICE - Nicelevel for grabcd-encode. ENCODE_PATH - Where to put the encoded files. == Limitations grabcd-scan and grabcd-rip always read from /dev/cdrom. This is because Audio::CD does not seem to have a configuration option for this. If icedax uses another device by default, you can set $CDDA_DEVICE to the correct one.