crip-3.9/0000755000000000000000000000000010702506256011023 5ustar rootrootcrip-3.9/TODO0000644000000000000000000000702510702356000011505 0ustar rootrootTo-Do list - (maybe one day, maybe never) ------------------------------------------------------------------------------- editfilenames (editcomment?) needs to use a filename/path specific tmp filenames so it can be used more than once at a time on a system! Have editfilenames doublecheck filename order after renaming to make sure it is the same as before. Also verify that no overwriting will happen before the rename - either with the old files or with each-other of the new files. editcomment: if tag file is empty or no change, it shouldn't rewrite the tag. Would like to get oggenc to output libvorbis-version/vendor-info for --info Feature: editcomment to handle multiple files & perhaps group labeling Change "cddevice" to just "device" (?) and move it before "encodeto =" line. Perhaps add info to the tag somehow that will indicate if any silence has been trimmed from the original rip (?) Consider having editcomment & editfilenames getting $editor from .criprc Expand on genres? (depending on if current convention has changed from the last time I checked) Have option (defaulted to ON) where the rip is piped straight to oggenc for an overall time-saver boost. Stephan Seitz's problem: getting $artist ("artist=") from the filename on sampler CDs where you get the title from the filename, should be able to get $artist too from the filename. Correct Timo's filename overwrite problem. More flexible filenaming conventions Support lame mp3 encoding with their new extended tagging support. Handling partial rips (such as "ghost tracks") better? (how?) bug: crip will overwrite existing files if the filenames given happen to be the same. crip should warn if any 2 or more files are the same name. Handle FLAC .ogg files better (?) (re)rip and encode using filename/tag info from a specified directory (crip will search directory for .ogg files that have the same discid and tracknumber and pull the data from there) charlton: A Possible idea is allowing a config file. It would be handy for people to set up their output settings eg. All files goto /media/{$artistname}/{$album}/{$track}-{$tracknum}.ogg This is flexible for the way certain people organise their music. Also a way to run the program using config file settings, so it doesn't ask you any questions. You can just set it and leave. | jomohke (~jeremy@dyn-ctb-203-221-73-46.webone.com.au) (Australia) : ircname : jeremy | channels : #gentoo | server : irc.freenode.net (http://freenode.net/) Perhaps order the tag items a little better (i.e. put things like "part=" right underneith "opus=") Be able to parse CDDB track titles into "artist / title" (and others) $settitle = "ask" (?) Verbosity levels Fork off an (interactive?) process that rips and encodes the files right after the track selection is entered. THEN ask for file/tag info while it is doing this. - A possibility for doing this might just be to combine the editfilenames & editcomment scripts, make them group-capable, and then run them on the set of files AFTER the ripping&encoding are done. Track variations support (multiple tracks in one track / indexing / etc.) (I don't know how I'd go about doing this, so it'll probably never happen) Simplify the structure of the whole script so that less code is repeated (I still feel it should be possible without the use of subroutines). *** If you can suggest any additional features or let me know a good way to implement the ones above, please let me know. Charlton Harrison charlton@dynet.com crip-3.9/crip0000755000000000000000000024151710702506214011712 0ustar rootroot#!/usr/bin/perl $version = "crip v3.9 (http://bach.dynet.com/crip)"; # Written to facilitate ripping & encoding CDs under Linux/UNIX # by Charlton Harrison (charlton@dynet.com) # # This script is intended to rip, encode and tag Ogg Vorbis and/or FLAC # digital music files from CD. If you want to make MP3s instead go back # to the past and use crip version 1.0. # # Defaults Section ------------------------------------------------------------ # Rather than edit these values here, it is better to edit them in the # ~/.criprc file, which is read in later... # encoders supported are "vorbis" and "flac" $encodeto = "vorbis"; # Flags for oggenc (Ogg Vorbis encoder) command. Only used only if # $encodeto is set to "vorbis". # Default is "-q 5" which is generally considered the point at which the # current vorbis codecs attain transparency to source (according to): # http://wiki.hydrogenaudio.org/index.php?title=Ogg_Vorbis # Make sure you are using the best vorbis codec (read this): # http://wiki.hydrogenaudio.org/index.php?title=Recommended_Ogg_Vorbis # Note that "-q 4" is a quality setting roughly equal to 128kbps (average) # and that "-q 3" (roughly 110kbps) is better than even 128kbps VBR MP3. # Hint: If you'd rather put these flags as a command-line option, # use: -o " -q 5" (with a space as the first character within the # quotes so as to not confuse the command-line parser) $oggencflags = "-q 5"; # $flacflags: Only used if $encodeto is set to "flac". # Note: if you include --ogg as a flag and encode to an ogg-formatted # flac file, crip will try to use metaflac to write the tags and that # seems to fail. I'm not sure what the best way to handle this scenario is. # If anyone out there wants to make flac files within the .ogg framework, # please enlighten me as to 1) why, and 2) what is one supposed to use to # modify comments in this .ogg file, vorbiscomment?! $flacflags = "--best --replay-gain"; # Flags for cdparanoia (CD ripper) command. # I like to use "-v -z" here. # If you find the "-v" is too verbose and pointless, feel free to take it # out. That would significantly reduce the size of your terminal output. # I find that using "-z" is good because I like knowing that when the script # finishes cdparanoia did not encounter anything that could lead to an # audible defect. However sometimes the script might hang indefinitely # because of the "-z". If you find that is the case, you can now ctrl-C # during the rip and set new options (say, to "-v --never-skip=40") so that # you can at least go back and listen to see if there were any audible # defects (most of the time there isn't even if the rip wasn't perfect). $cdparanoiaflags="-v -z"; # The first comment field in the tag-info will be: $comment0 = "Produced using " . $version . " on "; # ...followed by a date/time timestamp. $comment = ""; # An additional comment line might be specified in the .criprc file. # Get the title information that goes into the tag either from the # "filename" or the "cddb" info. # Default is "filename", because sometimes the CDDB info is wrong. # Note that if you set this to "cddb" but there isn't any CDDB info, # it'll just set it based on the filename anyway. $settitle = "filename"; # editnames: "off" = Use the legacy command-line to edit filenames; # "on" = use an editor; and "both" = use the command-line to edit the # filenames but also asks afterwards if you want to edit the filenames # with the editor. default = "on". $editnames = "on"; # Your favorite editor for editing filenames and tag files $editor = "vim"; # Default contact information (put YOUR e-mail address here!) # Remember to escape the '@' (by putting a '\' before it). # Example: $contact = "nobody\@nowhere.com"; $contact = ""; # Normalization is not necessary with replaygain/vorbisgain tags, so # turn off normalization by default. # This option can either be "on" or "off". $normalize = "off"; # Volume threshold - if peak vol > 1/$volthresh don't bother normalizing # Default is 1.078. If you set this value real high, your songs probably # won't be normalized but you'll still get the "not normalized, peak=X.XXX" # in your comment (you won't get this in your comment if normalize is off, # but you'll still have peak and group-peak info in your replaygain (vorbisgain) # tags, but these tags are not visible using xmms thru v1.2.7). # If normalize = "off" then $volthresh is ignored. $volthresh = 1.078; # $trimsilence can either be "on" or "off", depending on whether or not you # want to trim silence off the beginning & end of your track/group. # Note that if both trimsilence and normalize are off, you won't need sox. # I personally always set this to "on", but I'm defaulting it to "off" so # that the prerequisits aren't so tough. It doesn't seem to make much # difference in the final file size, interestingly. $trimsilence = "off"; # trimsilargs are the arguments that sox will take to trim the silence # from your tracks (if trimsilence is on in the first place). # A very safe setting is "silence 1 0:0:0.01 -96d" $trimsilargs = "silence 1 0:0:0.01 -96d"; # (i.e. anything louder than -96db for more than one hundredth of a second # will be considered the beginning of the sound. It doesn't work properly # on the end of the file because it processes forward. Logically, you # would start from the end of the file and work your way back to the first # detectable sounds, exactly like you did at the beginning of the file. # So you basically use the "reverse" option and re-run sox. This is # the actual recommended usage of the sox silence feature, which sucks # because you then have to make 2 passes. They'll probably change the # usage in the future and then I'll have to modify this script again. # Right now this works for 12.17.4 and 12.17.5 (and probably others)) # The type of media that the source comes from (default = "CD") # this just gets put in a comment $sourcemedia = "CD"; # Default genre to "classical" unless otherwise specified later. $genre = "classical"; # Default device to rip from $cddevice = "/dev/cdrom"; # Turn on/off deletion of wave and tag files. "on" by default. $delfiles = "on"; # Classical-style questioning defaults to "off" (because I'm assuming # most people will be ripping 'pop-style' CDs most of the time), $askclassical = "off"; # ...unless the genre winds-up being of the following, then it defaults # to "on" (values will be compared in a case-insensitive way). # Sometimes it's advantageous to have classical-style questioning for # labeling jazz music as well. #@classicalgenres = ("classical","jazz"); @classicalgenres = ("classical"); # Skip the album abbreviation question? # (turn this "on" if you never want to be asked for or have the album # abbreviation. If you rip a bunch of classical CDs and don't want # to have to answer null to the album abbreviation question every # time it's asked, but otherwise for non-classical CDs you want to # have the album abbreviation, set to "classical".) # "off", "on", or "classical" - default should be "classical". $skipalbumabv = "classical"; # Turn this on to skip the ripping process and create empty .wav files. # By turning this on you will automatically turn on $stopgap so that # you will have a chance to substitute the empty .wav files with the # .wav files that you presumably already have. $skiprip = "off"; # Add a 'stop-gap' between ripping and encoding in order for, say, # allowing user to edit the .wav files before continuing (some good # .wav file editors are: sweep, audacity). # This is done after the digital silence trimming. $stopgap = "off"; # Eject CD when done with it. "off" by default. $ejectcd = "off"; # Funny characters to allow (in default filenames) (other than [A-Z,a-z,0-9]) # Edit this string with care. Some chars have to be escaped ("\"), some # apparently have to be double-escaped ("//") (such as "(",")","[", and "]") # and some don't need to be escaped at all (such as the ",","á","é", etc.) $funnychars = "\-\'\",\\.\\[\\]\\(\\)"; # Map euro characters in the default filenames to American characters # (turn "on" if you are an American imperialist) $mapeurochars = "off"; # European characters to allow (if $mapeurochars is set to "off") # (again, this is only for the computer-chosen default filenames, which # are based on CDDB info. The tag info will automatically allow European # characters from CDDB or user sources.) $eurochars = "ÑñÁáÉéÍíÓóÚúÀàÈèÌìÒòÙùÄäËëÏïÖöÜüÂâÊêÎîÔôÛûÇçÃãÕõ´¸Ýý¾ÿ¦¨Ååß¼½Ææ"; # Allow spaces in filenames # I recommend leaving this off because it is bad form to have spaces in # filenames regardless of whether you are on UNIX or Windows. I have included # the option because there are too many Windoze users out there who flooded # the internet with sorry-ass MP3s made with bad encoders, no tag information, # and inappropriate file naming conventions, and who are still too used to # putting spaces in their filenames. I figure having this feature will # encourage them to use this script and make better quality files for # everyone. (no offense to the person who suggested me this feature) # So if you absolutely must have spaces in your filenames, turn # this to "on" (default is "off"). $allowspaces = "off"; # This is the e-mail address used to submit new entries to the freedb # CDDB database $cddbsubmitaddr = "freedb-submit\@freedb.org"; # Directory to write the cddb submit entry file (need to have write # permissions to this directory). $cddbsubmitdir = "/tmp"; # The following is the charset for the freedb-submit e-mail: $charset = "iso-8859-1"; # Now look and see what is in the .criprc file... open(CONFIG, "<" . $ENV{HOME} . "/.criprc"); while () { next if /^\#/; chomp; next unless $_; # skip empty lines s/\=/___EQ___/; # replace first equal sign ($key, $val) = split /___EQ___/; $key =~ s/[\t ]//g; # trim leading & trailing spaces $val = join " ", grep { $_ } split /[\t ]/, $val; ${$key} = $val; ##print "Key: ",$key, " Val: ", $val, "\n"; } close CONFIG; # Set the following variable to "" if you do not want to receive copies of # the CDDB submissions that you make. $cddbsubmitaddrCc = $contact; # Default is to use cddb protocol to access cddb server without proxy. $cddbproxy = {}; # End of Defaults Section ----------------------------------------------------- # Allow the user to override the defaults from the command line... #use Getopt::Std; use Getopt::Long; $Getopt::Long::ignorecase = 0; $USAGE = "$0 [options] Options: -h, --help Print this help then exit -i, --info Print crip variable information then exit -v, --version Print version of crip then exit -e codec Encode to vorbis or flac (default = $encodeto) -s media Specify the source media (default = $sourcemedia) -g genre Specify the music genre (default = $genre) -q [on/off] Classical-style questioning (default = $askclassical) -m [on/off] Map European to American-only chars (default = $mapeurochars) -t [on/off] Trim leading/trailing silence (default = $trimsilence) -n [on/off] Normalize the audio (default = $normalize) -V volthresh Volume threshold for normalizing (default = $volthresh) (only used when normalizing is enabled) -r [on/off] Remove files after encoding (default = $delfiles) -E editor Editor to use (default = $editor) -u [on/off/both] Use editor to name the files (default = $editnames) (as opposed to the command-line) -o \" flags\" Flags to pass to oggenc (default = '$oggencflags') -f \" flags\" Flags to pass to flac (default = '$flacflags') -c \" flags\" Flags to pass to cdparanoia (default = '$cdparanoiaflags') -d device CDrom device to read from (default = $cddevice) -w [on/off] Skip the ripping (makes empty .wav files) (default = $skiprip) (useful if you already have the .wav files to encode) -p [on/off] Prompt to continue after ripping (default = $stopgap) (useful pause to edit .wav files before encoding) -x [on/off] Eject CD when done ripping (default = $ejectcd) -P proxyserver Pass an http proxy to CDDB_get if necessary "; GetOptions("v","version","i","info","h","help","s=s","g=s","d=s","e=s","E=s","V=f","P=s","u:s","o:s","f:s","c:s","q:s","m:s","t:s","n:s","r:s","w:s","p:s","x:s") || die "$USAGE"; if ((defined $opt_h) || (defined $opt_help)) { print "$USAGE"; exit(); } if ((defined $opt_v) || (defined $opt_version)) { print "$version\n"; exit(); } $sourcemedia = $opt_s if (defined $opt_s); $genre = $opt_g if (defined $opt_g); $askclassicalflag = $opt_q if (defined $opt_q); $mapeurochars = $opt_m if (defined $opt_m); $editnames = $opt_u if (defined $opt_u); $encodeto = $opt_e if (defined $opt_e); $editor = $opt_E if (defined $opt_E); $normalize = $opt_n if (defined $opt_n); $volthresh = $opt_V if (defined $opt_V); $trimsilence = $opt_t if (defined $opt_t); $delfiles = $opt_r if (defined $opt_r); $oggencflags = $opt_o if (defined $opt_o); $flacflags = $opt_f if (defined $opt_f); $cdparanoiaflags = $opt_c if (defined $opt_c); $cddevice = $opt_d if (defined $opt_d); $skiprip = $opt_w if (defined $opt_w); $stopgap = $opt_p if (defined $opt_p); $ejectcd = $opt_x if (defined $opt_x); $cddbproxy = { HTTP_PROXY=>$opt_P, CDDB_MODE=>'http'} if (defined $opt_P); if ($normalize eq "") { $normalize = "on"; } if (($normalize ne "on") && ($normalize ne "off")) { die "Unknown normalize (-n) setting ($normalize)!\n$USAGE"; } if ($trimsilence eq "") { $trimsilence = "on"; } if (($trimsilence ne "on") && ($trimsilence ne "off")) { die "Unknown trim silence (-t) setting ($trimsilence)!\n$USAGE"; } if ($editnames eq "") { $editnames = "on"; } if (($editnames ne "on") && ($editnames ne "off") && ($editnames ne "both")) { die "Unknown editnames (-f) setting ($editnames)!\n$USAGE"; } if ($encodeto eq "") { print "Did not specify a codec to encode to. Assuming \"vorbis\".\n"; $encodeto = "vorbis"; } if (($encodeto ne "vorbis") && ($encodeto ne "flac")) { die "Invalid/unsupported codec (-e) ($encodeto).\n$USAGE"; } if ($mapeurochars eq "") { $mapeurochars = "on"; } if (($mapeurochars ne "on") && ($mapeurochars ne "off")) { die "Unknown mapeurochars (-m) setting ($mapeurochars)!\n$USAGE"; } if ($delfiles eq "") { $delfiles = "on"; } if (($delfiles ne "on") && ($delfiles ne "off")) { die "Unknown delete (-r) setting ($delfiles)!\n$USAGE"; } if ($skiprip eq "") { $skiprip = "on"; } if (($skiprip ne "on") && ($skiprip ne "off")) { die "Unknown skiprip (-w) setting ($skiprip)!\n$USAGE"; } if ($skiprip eq "on") { $stopgap = "on"; } if ($stopgap eq "") { $stopgap = "on"; } if (($stopgap ne "on") && ($stopgap ne "off")) { die "Unknown stopgap (-p) setting ($stopgap)!\n$USAGE"; } if ($ejectcd eq "") { $ejectcd = "on"; } if (($ejectcd ne "on") && ($ejectcd ne "off")) { die "Unknown eject (-x) setting ($ejectcd)!\n$USAGE"; } if ((defined $opt_V) && ($normalize eq "off")) { print "You specified a volume threshold,\n"; print "but you also have normalization turned off.\n\n"; die "$USAGE"; } if (defined $askclassicalflag) { if ($askclassicalflag eq "") { $askclassicalflag = "on"; } if (($askclassicalflag ne "on") && ($askclassicalflag ne "off")) { die "Unknown classical (-q) setting ($askclassicalflag)!\n$USAGE"; } } if (! -e $cddevice) { die "No such device: $cddevice!\n$USAGE"; } # End getopts section # Print current version of crip print $version, "\n"; # Print my feedback contact information print "\n Please report all bugs, feature requests, or\n"; print " general difficulties to charlton\@dynet.com.\n\n"; # List options and what they're set to print "Options currently set to:\n"; print " contact = $contact\n"; print " sourcemedia = $sourcemedia\n"; print " encodeto = $encodeto\n"; print " cddevice = $cddevice\n"; print " settitle = $settitle\n"; print " editnames = $editnames\n"; print " editor = $editor\n"; print " askclassical (default) = $askclassical\n"; if (defined $askclassicalflag) { print " askclassicalflag = $askclassicalflag\n"; } if ($skipalbumabv eq "classical") { print " skipalbumabv set only for: @classicalgenres\n"; } else { print " skipalbumabv = $skipalbumabv\n"; } print " mapeurochars = $mapeurochars\n"; print " normalize = $normalize\n"; if ($normalize eq "on") { print " volthresh = $volthresh\n"; } print " trimsilence = $trimsilence\n"; if ($trimsilence eq "on") { print " trimsilargs = $trimsilargs\n"; } print " delfiles = $delfiles\n"; print " skiprip = $skiprip\n"; print " stopgap = $stopgap\n"; print " ejectcd = $ejectcd\n"; print "\n"; # Print ripper info $cdprelease = `cdparanoia --version 2>&1 | grep release`; chop $cdprelease; print "Ripper: ", $cdprelease, " ", $cdparanoiaflags, "\n"; if ((defined $opt_c) && ($cdparanoiaflags eq "")) { print "\nWARNING: Did not specify any flags for cdparanoia.\n"; print " Will run cdparanoia without any flags.\n\n"; } if ((defined $opt_f) && ($flacflags eq "")) { if ($encodeto eq "flac") { print "\nWARNING: Did not specify any flags for flac.\n"; print " Will run flac without any flags.\n\n"; } else { print "\nWARNING: You specified the '-f' flag but you\n"; print " are not encoding to flac!\n\n"; } } # Set the encoding field if ($encodeto eq "vorbis") { $encoding = `oggenc --version`; chop $encoding; # $encoding = $encoding . " (aoTuV-b3 patched) " . $oggencflags; $encoding = $encoding . " " . $oggencflags; } else { $encoding = `flac --version`; chop $encoding; $encoding = $encoding . " " . $flacflags; } print "Encoder: ", $encoding, "\n"; if ((defined $opt_i) || (defined $opt_info)) { print "\n"; exit(); } if ((defined $opt_o) && ($oggencflags eq "")) { if ($encodeto eq "vorbis") { print "\nWARNING: Did not specify any flags for oggenc.\n"; print " Will encode with no flags!\n"; } else { print "\nWARNING: You specified the '-o' flag but you\n"; print " are not encoding to vorbis!\n\n"; } } print "\n"; ##exit(); # Used for testing command-line option behavior # Now check to make sure all required components are available # Check for the encoder and necessary tagging tools if ($encodeto eq "vorbis") { $out = `which oggenc`; if ($out eq "") { die "Cannot find `oggenc` for encoding to Ogg Vorbis!\n"; } $out = `which vorbiscomment`; if ($out eq "") { die "Cannot find `vorbiscomment` for tagging the Ogg Vorbis files!\n"; } } else { $out = `which flac`; if ($out eq "") { die "Cannot find `flac`!\n"; } $out = `which metaflac`; if ($out eq "") { die "Cannot find `metaflac` for tagging the flac files!\n"; } else { # metaflac exists, get its version number $mfver = `metaflac --version`; chop $mfver; $mfver =~ m/(\d+\..+)/; $mfver = $1; } } # Unless normalize is on or not encoding to vorbis, check for vorbisgain unless (($normalize eq "on") || ($encodeto ne "vorbis")) { # If vorbisgain is unavailable then deliver this warning. $out = `which vorbisgain`; if ($out eq "") { print "\nIt does not appear that vorbisgain is available on\n"; print "this system. Either get it (recommended) or turn on\n"; print "normalization instead (not recommended).\n"; print "Either ctrl-C now or press to continue: "; $inp = ; } } if ($editnames eq "on") { $out = `which $editor`; if ($out eq "") { print "\nYou have 'editnames' on, and you have your editor set to '$editor',\n"; print " but there is no $editor in your path. You need to either install\n"; print " this editor in your path, change your editor to an available editor\n"; print " in your path, or turn 'editnames' off.\n"; exit(); } } if (($normalize eq "on") || ($trimsilence eq "on")) { $out = `which sox`; if ($out eq "") { print "\nsox needs to be installed.\n\n"; print "Note: You can eliminate your dependency on sox by turning off\n"; if (($normalize eq "on") && ($trimsilence eq "on")) { print " normalization and silence trimming.\n"; } elsif ($trimsilence eq "on") { print " silence trimming.\n"; } elsif ($normalize eq "on") { print " normalization.\n"; } exit(); } else { $out = `sox -h 2>&1 | grep Version`; chop $out; $out =~ m/Version (.+)/; $soxver = $1; $soxver =~ m/(\d+)\.(.+)/; $soxver1 = $1; $soxver2 = $2; #print $out, "\n", $soxver, " | ", $soxver1, "|", $soxver2, "\n"; #if ($soxver2 < "17.6") { print "here\n"; } #exit(); if (($soxver1 < "12") || (($soxver1 == "12") && ($soxver2 lt "17.4"))) { print "Your sox needs to be updated.\n"; print "Silence trimming works differently in versions before sox-12.17.4.\n"; print "Note: You can eliminate your dependency on sox by turning off\n"; if (($normalize eq "on") && ($trimsilence eq "on")) { print " normalization and silence trimming.\n"; } elsif ($trimsilence eq "on") { print " silence trimming.\n"; } elsif ($normalize eq "on") { print " normalization.\n"; } exit(); } } } # This will bomb with an error if not available: use FindBin; use CDDB_get qw( get_cddb get_discids ); # Check for existing *.wav, *.tag, *.ogg, *.flac or filenames.txt files $out = `ls *.wav *.ogg *.flac *.tag 2>/dev/null`; if ($out ne "") { print "You currently have *.wav, *.ogg, *.flac, or *.tag files in the current\n"; print "working directory. These are subject to being overwritten.\n\n"; print "Press to proceed (or ctrl-C to abort): "; $inp = ; } if (-e "filenames.txt") { print "You currently have a filenames.txt file in the current working\n"; print "working directory. This will be deleted!\n\n"; print "Press to proceed (or ctrl-C to abort): "; $inp = ; # Go ahead and delete the file now so that if the script is stopped and # restarted this question won't keep bugging the user. print "Deleting filenames.txt\n\n"; `rm filenames.txt`; } # End of check components section. # Main loop while (1) { $firstdate = 1; # cddb query print "Retrieving Disc Information...\n"; $ids = get_discids($cddevice); $discid = sprintf "%08x", $ids->[0]; $totaltracks = $ids->[1]; $toc = $ids->[2]; print "Retrieving CDDB Information...\n"; # %cd = get_cddb(); eval { %cd = get_cddb($cddbproxy); }; if ($@) { print "error: $!\n\n"; print "get_cddb() has failed for some reason.\n"; print "Perhaps the network is down?\n"; } print "\n"; print "DiscID: ", $discid, "\n"; unless(defined $cd{title}) { print "No CDDB info found.\n"; } else { print "cddbID: ", $cd{id}, "\n"; print "artist: ", $cd{artist}, "\n"; print "title: ", $cd{title}, "\n"; print "category: ", $cd{cat}, "\n\n"; $genre = $cd{cat}; if ($cd{tno} != $totaltracks) { print "!!! WARNING !!!\n"; print "Reported number of tracks different from actual.\n"; print "Disc reports ", $totaltracks, ".\n"; print "CDDB reports ", $cd{tno}, ".\n\n"; } } print "total number of tracks: ", $totaltracks, "\n"; $tr=1; foreach $trtitle ( @{cd->{track}} ) { $trname[$tr] = $trtitle; $from=$toc->[$tr-1]{frames}; $to=$toc->[$tr]{frames} - 1; $dur=$to-$from; $min=int($dur/75/60); $sec=int($dur/75)-$min*60; $frm=($dur-$sec*75-$min*75*60)*100/75; $out=sprintf "track %2d: %8d - %8d [%2d:%.2d.%.2d]: $trtitle\n",$tr,$from,$to,$min,$sec,$frm; print "$out"; $tr++; } print "\n"; ############################################################### CDDB test info #foreach $tmp (0 .. ($totaltracks - 1)) { # print $tmp, " - ", $toc->[$tmp]{frames}, "\n"; #} #$cddbduration = int($toc->[$totaltracks]{frames} / 75); #print "Duration: ", $cddbduration, " seconds.\n"; #foreach $idx (@{cd->{raw}}) { # if ($idx =~ m/^#\s+Revision:\s*(\d+)/) { $revision = $1; } # print $idx; #} #print "\nRevision: ", $revision, "\n"; ############################################################################## ##exit(); # Request normalization groupings print "\n\nEnter the track numbers for each group (each group will be\n"; print "replaygained/vorbisgained/normalized, trimmed, and tagged\n"; print "as if it were one piece of music).\n\n"; print "Delimit the track numbers on each line by a space.\n"; print "Type \"end\" to go on to the next section.\n\n"; print "Note that only the tracks you specify will be ripped.\n"; print "Also note that if you list a track more than once, it will be\n"; print "unnecessarily ripped more than once (so don't do it).\n"; print "You can also enter \"all\" or \"each\" for grouping all tracks as\n"; print "one group, or each track as a separate group respectively.\n"; print "If input is \"all\" or \"each\" then the entire CD is ripped.\n"; $inp = ""; $listing = ""; $listnum = 0; while ($inp ne "end") { print "\n> "; $inp = ; chop $inp; if ($inp eq "all") { $i = 1; while ($i <= $totaltracks) { $list[$listnum][$i-1] = $i; $i++; } $listing = "all"; $inp = "end"; } elsif ($inp eq "each") { $i = 1; while ($i <= $totaltracks) { $list[$listnum][0] = $i; $listnum++; $i++; } $listing = "each"; $inp = "end"; } elsif ($inp ne "end") { # Parse the list of numbers # If $inp is not a list of numbers then print "invalid" $valid = 0; $i = 0; while ($inp =~ s/^(\d+)\s*//) { $list[$listnum][$i] = $1; $valid = 1; $i++; } if ($valid) { $listnum++; } else { print "Invalid Entry.\n\n"; } } } # Reiterate the lists... print "\n\nHere are the lists of tracks you picked:\n\n"; $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { print $list[$listnum][$index], " "; $index++; } $listnum++; print "\n"; } print "\n"; # Analyze picked tracks and display any warning messages if necessary # 1) check to see if any of the tracks are listed more than once $warning = 0; $tmpindex = 0; $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { $tmptrack = $list[$listnum][$index]; # Check if $tmptrack matches any from the array before it $chkindex = 0; while ($chkindex < $tmpindex) { if ($tmptrack == $tmptracks[$chkindex]) { $warning = 1; } $chkindex++; } # Add $tmptrack to the array $tmptracks[$tmpindex] = $tmptrack; $tmpindex++; $index++; } $listnum++; } if ($warning) { print "Warning: Some track(s) in the list appear more than once.\n"; } # 2) check to see if any of the tracks don't appear $warning = 0; $listnum = 0; foreach $tmptrack (1 .. $totaltracks) { # Make sure each $tmptrack appears at least once $matched = 0; $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { if ($tmptrack == $list[$listnum][$index]) { $matched = 1; } $index++; } $listnum++; } if (!$matched) { $warning = 1;} } if ($warning) { print "Warning: Some track(s) on the CD don't appear in your listed tracks.\n"; } # 3) check to make sure all lists are in consecutive order $warning = 0; $listnum = 0; while ($listnum <= $#list) { # Make sure each of these lists is in consecutive order $index = 0; $lasttrack = 0; while ($index <= $#{$list[$listnum]}) { if ($lasttrack != 0) { if ($list[$listnum][$index] != ($lasttrack + 1)) { $warning = 1; } } $lasttrack = $list[$listnum][$index]; $index++; } $listnum++; } if ($warning) { print "Warning: Some list(s) are not in consecutive order.\n"; } # 4) check to make sure all the tracks are within the bounds of the CD. $warning = 0; $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { if (($list[$listnum][$index] < 1) || ($list[$listnum][$index] > $totaltracks)) { $warning = 1; } $index++; } $listnum++; } if ($warning) { print "Warning: Some track(s) you listed are not on the CD (these won't be ripped).\n"; print "FYI: Total number of tracks disc reports: $totaltracks\n"; } print "\n"; # Query section begins... print "Please enter the genre for this album.\n"; print "Recommended genres are (from freedb.org):\n"; print " blues (self explanatory)\n"; print " classical (self explanatory)\n"; print " country (self explanatory)\n"; print " folk (self explanatory)\n"; print " jazz (self explanatory)\n"; print " newage (self explanatory)\n"; print " reggae (self explanatory)\n"; print " rock (including funk, soul, rap, pop, industrial, metal, etc.)\n"; print " soundtrack (movies, shows)\n"; print " data (ISO9660 and other data CDs)\n"; print " misc (others that do not fit in the above categories)\n"; print "Enter the genre for this album (single space = null): [", $genre, "]: "; $inp = ; chop($inp); if ($inp ne "") { $genre = $inp; } if ($inp eq " ") { $genre = ""; } if ($genre =~ m/new\.age/i) { print "\"$genre\" -> \"newage\"\n"; $genre = "newage"; } # If the '-q' flag was used, override default if (defined $askclassicalflag) { # We already know from above that $askclassicalflag must be "on" or "off" $askclassical = $askclassicalflag; } else { # Set $askclassical if $genre is one of @classicalgenres foreach $classicalgenre (@classicalgenres) { if ($genre =~ m/^\s*$classicalgenre\s*$/i) { $askclassical = "on"; } } } # Set $setlabels default $setlabels = "cd"; $composer = ""; $complast = ""; if ($askclassical eq "on") { print "Since this is $genre, there should be a composer.\n"; if ($#list >= 1) { # (more than one list) print "If the composer is different for each group/list, just set the\n"; print "value to null and add the composer tag manually with each list.\n"; } # Get $composer $composer = $cd{artist}; print "Enter composer (single space = null): [", $composer, "]: "; $inp = ; chop($inp); if ($inp ne "") { $composer = $inp; } if ($inp eq " ") { $composer = ""; } # Now try to set $complast to the last name of the $composer if ($composer =~ m/^\s*(\S+)\s*,/) { $complast = $1; } elsif ($composer =~ m/\s+(\S+)\s*$/) { $complast = $1; } else { $complast = $composer; } # Since this is Classical-style questioning, default $setlabels to "list". # ($setlabels default will be reset if $listing eq "each" or "all") $setlabels = "list"; } # Ask query to what $setlabels will actually be # (this will determine whether to label once for the whole CD or # once for each list) # But don't even bother if $listing is "each" or "all" if (($listing ne "each") && ($listing ne "all")) { if ($#list >= 1) { print "Would you like to set the artist and miscellaneous labeling info for\n"; print "the whole CD right now, or would you prefer to set it for each list?\n"; print "(list/cd) [" . $setlabels . "]: "; $inp = ; chop($inp); if (($inp eq "list") || ($inp eq "LIST")) { $setlabels = "list"; } if (($inp eq "cd") || ($inp eq "CD")) { $setlabels = "cd"; } } else { # Don't bother asking this question if the number of lists is just one. $setlabels = "cd"; } } else { # $listing is "each" or "all" so it's probably safe to assume that # the user doesn't want to label per list. $setlabels = "cd"; # But if the user selected "each", print a message anyway just to # let the user know that if he wants to label each list, he'll have # to start the script over and enter in each track as a separate list. if (($listing eq "each") && ($#list >= 1)) { print "Note: Since you entered \"each\", I will assume that you will\n"; print " want to enter all information just once rather than per list.\n"; } } # Set default $artist now if $setlabels eq "cd" $artist = $cd{artist}; $conductor = ""; $performer = ""; $ensemble = ""; if ($setlabels eq "cd") { # Set the $artist now if ($askclassical eq "on") { print "Enter conductor. If there isn't one, enter null.\n"; print " (single space = null): [", $artist, "]: "; $inp = ; chop($inp); if ($inp eq "") { $conductor = $artist; } else { $conductor = $inp; } if ($inp eq " ") { $conductor = ""; } if ($conductor ne "") { print "You have entered a conductor so this will be your artist's name.\n"; $artist = $conductor; } else { print "Since there is no conductor, there's probably a (main) performer.\n"; print "Enter this performer (single space = null): [", $artist, "]: "; $inp = ; chop($inp); if ($inp eq "") { $performer = $artist; } else { $performer = $inp; } if ($inp eq " ") { $performer = ""; } if ($performer ne "") { print "You have entered a performer so this will be your artist's name.\n"; $artist = $performer; } else { print "Since there is no main performer or conductor,\n"; print " the 'artist' is probably an ensemble.\n"; print "If this is true, enter the name of the ensemble (single space = null): [", $artist, "]: "; $inp = ; chop($inp); if ($inp eq "") { $ensemble = $artist; } else { $ensemble = $inp; } if ($inp eq " ") { $ensemble = ""; } if ($ensemble ne "") { print "You have entered an ensemble so this will be your 'artist'.\n"; $artist = $ensemble; } else { print "Okay, just enter the artist then.\n"; print "Enter artist (single space = null): [", $artist, "]: "; $inp = ; chop($inp); if ($inp ne "") { $artist = $inp; } if ($inp eq " ") { $artist = ""; } } } } } else { print "Enter artist (single space = null): [", $artist, "]: "; $inp = ; chop($inp); if ($inp ne "") { $artist = $inp; } if ($inp eq " ") { $artist = ""; } } } # Set $album (the album title) $default = $cd{title}; $default =~ s/\r//g; # Get rid of this common char that causes problems print "Enter album name (single space = null): [", $default, "]: "; $inp = ; chop($inp); if ($inp eq "") { $album = $default; } else { $album = $inp; } if ($inp eq " ") { $album = ""; } # Set $albumabv (the album abbreviation). This is only used to help # set the default track names. if (($skipalbumabv eq "on") || (($skipalbumabv eq "classical") && ($askclassical eq "on"))) { # If classical, you probably don't want the default name to include # an album abbreviation. If you do, name the files manually. $albumabv = ""; } else { # Set $albumabv to the first four first-letters of the $album $albumabv = $album; $albumabv =~ s/_/ /g; $tmp = ""; if ($albumabv =~ s/([\w$eurochars]+)//) { $tmp = substr($1, 0, 1); } if ($albumabv =~ s/([\w$eurochars]+)//) { $tmp = $tmp . substr($1, 0, 1); } if ($albumabv =~ s/([\w$eurochars]+)//) { $tmp = $tmp . substr($1, 0, 1); } if ($albumabv =~ s/([\w$eurochars]+)//) { $tmp = $tmp . substr($1, 0, 1); } $albumabv = $tmp; print "Enter album abbreviation (single space = null): [", $albumabv, "]: "; $inp = ; chop($inp); unless ($inp eq "") { $albumabv = $inp; } if ($inp eq " ") { $albumabv = ""; } } # Set the $label and $labelno print "Enter label name (single space = null): []: "; $inp = ; chop($inp); if (($inp eq "") || ($inp eq " ")) { $label = ""; } else { $label = $inp; } # Set $labelno print "Enter label catalog number (single space = null): []: "; $inp = ; chop($inp); if (($inp eq "") || ($inp eq " ")) { $labelno = ""; } else { $labelno = $inp; } # Set $recdate # Incidently, the date of the recording is one of those things that I want # to ask for every list, even if $setlabels="cd". But if the $listing is # "all" or "each" then I'll just ask it once right now. $recdate = ""; if (($listing eq "all") || ($listing eq "each")) { # Set $recdate for ALL the tracks here and now... if ($firstdate) { print "Enter the date of recording -\n"; print "\n(formatting notes: no format is specifically required, but it is definitely\n"; print " preferable to include all FOUR digits of the year, and since it'll never\n"; print " always be clear whether it's MM-DD or DD-MM, it is actually preferable\n"; print " to spell out the month (at least the first 3 letters anyway) and then the day,\n"; print " but if you really want to use a numeric format, chose the ISO-8601 standard\n"; print " (YYYY-MM-DD), however note that it may still be unclear to some which number\n"; print " is the month and which is the day. So it is recommended that you use dates\n"; print " such as \"March 24, 1994\", \"March, 1994\", or \"1994\" (depending on how much\n"; print " information you have), and if all you have is the production (P) date, put\n"; print " \"(P)1994\". The actual recording date is usually up to a year or two before\n"; print " the production date.\n"; $firstdate = 0; } print "Enter the date of recording (single space = null): [don't put one]: "; $inp = ; chop($inp); $recdate = $inp; if ($inp eq " ") { $recdate = ""; } } # If $setlabels ne "list", set other tag fields here... if ($setlabels ne "list") { print "\nType the name of a field tag that you'd like to add to\n"; print " all these music files (or make up your own field tag name).\n"; print "You can enter the fieldname then enter the data for that fieldname,\n"; print "or you can enter fieldname=data all on one line.\n"; # List some possible recommended tags print "\nPossible tag recommendations:\n"; if ($askclassical eq "on") { if ($composer eq "") { print " composer"; } if ($conductor eq "") { print " conductor"; } if ($ensemble eq "") { print " ensemble"; } print " opus\n"; } print " location performer copyright license\n\n"; # Continue print "Just press (with nothing on the line) to finish:\n"; $finished = 0; $tagindex = 0; while (!$finished) { $inp = ; chop $inp; if (($inp ne "") && ($inp ne " ") && ($inp ne ".")) { # If there's an "=" assume the line is "fieldname=data" if ($inp =~ m/=/) { $tag[$tagindex] = $inp; } else { # There is no "=". Assume the line is just the fieldname. $tagname = $inp; print "Set " . $tagname . "="; $inp = ; chop $inp; $tagdata = $inp; $tag[$tagindex] = $tagname . "=" . $tagdata; } $tagindex++; } else { $finished = 1; } } } # Filename Setting Section print "\nTrack/filename labeling section...\n"; # Set all the default track names $i = 1; while ($i <= $totaltracks) { if ($i < 10) { $tmpindex = "0" . $i; } else { $tmpindex = $i; } $tn2 = $trname[$i]; $tocorigname = $tn2; # If there's no useful info in $tn2, set it to "track_??" unless ($tn2 =~ m/\w/) { $tn2 = "track_" . $tmpindex; } if ($complast ne "") { $tn0 = $complast; $tn0 = $tn0 . "_-_"; } elsif ($artist ne "") { $tn0 = $artist; $tn0 = $tn0 . "_-_"; } else { $tn0 = ""; } if ($albumabv eq "") { $tn1 = ""; } else { $tn1 = $albumabv . $tmpindex . "_"; } unless(defined $cd{title}) { if ($album eq "") { $album = "CDDB info not available"; } } # Set default filename from its components # $tmpname = $artist . "_-_" . $albumabv . $tmpindex . "_" . $title; $tmpname = $tn0 . $tn1 . $tn2; # Process $tmpname $tmpname =~ s/\s+/_/g; # Substitute white-space character blocks with "_" # Map special chars to other allowable chars $tmpname =~ s/[\/\\~]/-/g; # Replace any of these chars with a "-" $tmpname =~ s//)/g; # Substitute <> with () $tmpname =~ s/{/[/g; $tmpname =~ s/}/]/g; # Substitute {} with [] $tmpname =~ s/\&/_and_/g; # Replace & with "and" (double-"_" will be taken out later) if ($mapeurochars eq "on") { # Map euro-characters to American characters $tmpname =~ s/[áàäâãå]/a/g; $tmpname =~ s/[ÁÀÄÂÃÅ]/A/g; $tmpname =~ s/[éèëê]/e/g; $tmpname =~ s/[ÉÈËÊ]/E/g; $tmpname =~ s/[íìïî]/i/g; $tmpname =~ s/[ÍÌÏÎ]/I/g; $tmpname =~ s/[óòöôõð]/o/g; $tmpname =~ s/[ÓÒÖÔÕ]/O/g; $tmpname =~ s/[úùüû]/u/g; $tmpname =~ s/[ÚÙÜÛ]/U/g; $tmpname =~ s/[ñ]/n/g; $tmpname =~ s/[Ñ]/N/g; $tmpname =~ s/[ç]/c/g; $tmpname =~ s/[Ç]/C/g; $tmpname =~ s/[¨]/s/g; $tmpname =~ s/[¦]/S/g; $tmpname =~ s/[ýÿ]/y/g; $tmpname =~ s/[ݾ]/Y/g; $tmpname =~ s/[¸]/z/g; $tmpname =~ s/[´]/Z/g; $tmpname =~ s/[æ]/ae/g; $tmpname =~ s/[Æ]/AE/g; $tmpname =~ s/[½]/oe/g; $tmpname =~ s/[¼]/OE/g; $tmpname =~ s/[ß]/B/g; } # Now get rid of the rest (of the special chars) $tmpname =~ s/[^\w$funnychars$eurochars]//g; # Only keep specified $funnychars and $eurochars $tmpname =~ s/__/_/g; # Get rid of any double-blanks caused by the last line $tmpname =~ s/(,_|_,)/,/g; $tmpname =~ s/(\._|_\.)/./g; # Rid more extraneous "_"s if ($allowspaces eq "on") { # Replace all suggested "_" with " " # Easier doing this once at the end of the process than # making many exceptions from the beginning $tmpname =~ s/_/ /g; } # Done. $tmpname will now be the default (computer-generated) filename $tocname[$tmpindex] = $tmpname; $tocorigname[$tmpindex] = $tocorigname; $i++; } # If $album is empty set it to $albumabv unless ($album =~ m/\S+/) { $album = $albumabv; } # User interaction begins for filename selection... if ($editnames eq "on") { print "Here are the computer-chosen filenames for the tracks that you've picked:\n"; # Create the filenames.txt file now open(NAMEFILE, ">filenames.txt"); $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { print NAMEFILE "$tocname[$list[$listnum][$index]]\n"; $index++; } print NAMEFILE "\n"; $listnum++; } close(NAMEFILE); # Assume the computer-generated defaults aren't broken! $broken = 0; $warning = 0; $firstpass = 1; do { # Print out the filenames.txt file to the screen print "-------------------------------------------------------------------------------\n"; open(NAMEFILE, "filenames.txt"); while ($line = ) { # Process $line just like the filenames would be before showing them chop $line; $line =~ s/^\s*//; $line =~ s/\s*$//; print $line, "\n"; } close(NAMEFILE); # Query $default = "no"; if ($warning) { print $warningmsg; $default = "yes"; } if ($broken) { print $reason; $default = "yes"; } if ($firstpass) { $default = "yes"; } print "Edit the above filenames? [" . $default . "]: "; $inp=; chop($inp); if ($inp eq "") { $inp = $default; } $inp =~ s/\s//g; if ($inp =~ m/^\s*y/i) { system "$editor filenames.txt"; $firstpass = 0; } # Process filenames.txt into $oname[][] and $name[][] $broken = 0; # Will set this to 1 if the file is discovered to be broken $warning = 0; open(NAMEFILE, "filenames.txt"); $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { $oname[$listnum][$index] = ; chop $oname[$listnum][$index]; # Clear off any whitespace at the beginning or end of string $oname[$listnum][$index] =~ s/^\s*//; $oname[$listnum][$index] =~ s/\s*$//; # But there are any spaces left set $broken if (($oname[$listnum][$index] =~ m/\s/) && ($allowspaces ne "on")) { $broken = 1; $reason = "No spaces allowed in filenames.\n"; } unless ($oname[$listnum][$index] =~ m/\w/) { $broken = 1; $reason = "Invalid filename detected (no word characters).\n"; } if ($oname[$listnum][$index] eq "") { $broken = 1; $reason = "There must be one (and only one) empty line between each list.\n"; } if ($oname[$listnum][$index] =~ m/\.(ogg|mp3|wav)$/i) { # Not broken, but print a notice and set default to edit again. $warning = 1; $warningmsg = "Warning: You are not supposed to end your filenames with an extension here.\n"; } $name[$listnum][$index] = $oname[$listnum][$index]; # Add escapes to the appropriate characters # Replace (, ), ', ` chars with \(, \), \', \`, etc. $name[$listnum][$index] =~ s/\(/\\(/g; $name[$listnum][$index] =~ s/\)/\\)/g; $name[$listnum][$index] =~ s/'/\\'/g; $name[$listnum][$index] =~ s/`/\\`/g; $name[$listnum][$index] =~ s/\"/\\\"/g; $name[$listnum][$index] =~ s/ /\\ /g; $name[$listnum][$index] =~ s/\;/\\\;/g; $name[$listnum][$index] =~ s/,/\\,/g; $name[$listnum][$index] =~ s/&/\\&/g; $name[$listnum][$index] =~ s/\$/\\\$/g; $index++; } $emptyline = ; chop $emptyline; $emptyline =~ s/\s//g; if ($emptyline ne "") { $broken = 1; $emptyline = "not_empty"; $reason = "There cannot be empty lines within a list.\n"; } $listnum++; } # If the names do not process go thru the loop again } until (($inp eq "no") && (!$broken)); } else { print "NOTE: If you make a mistake during this section, you can\n"; print " enter a single space to go backwards in the list(s). You\n"; print " will then get a chance to redo the previous item(s).\n"; } $listnum = 0; while ($listnum <= $#list) { if ($editnames eq "on") { if (($setlabels eq "list") || (($listing ne "all") && ($listing ne "each"))) { print "\n\n-------------------------------------------------------------------------------\n"; print "Enter information for the list:\n\n"; # Print out the filenames in this list $index = 0; while ($index <= $#{$list[$listnum]}) { print "$oname[$listnum][$index]\n"; $index++; } print "\n"; } } else { print "\nNew List\n\n"; $index = 0; while ($index <= $#{$list[$listnum]}) { print "Name for track ", $list[$listnum][$index], " - "; # $oname[][] will be the filename BEFORE inserting '\'s (for certain chars) $oname[$listnum][$index] = $tocname[$list[$listnum][$index]]; $name[$listnum][$index] = $tocname[$list[$listnum][$index]]; # Replace (, ), ', ` chars with \(, \), \', \` *** - Might need to add on this later $name[$listnum][$index] =~ s/\(/\\(/g; $name[$listnum][$index] =~ s/\)/\\)/g; $name[$listnum][$index] =~ s/'/\\'/g; $name[$listnum][$index] =~ s/`/\\`/g; $name[$listnum][$index] =~ s/\"/\\\"/g; $name[$listnum][$index] =~ s/ /\\ /g; $name[$listnum][$index] =~ s/\;/\\\;/g; $name[$listnum][$index] =~ s/,/\\,/g; $name[$listnum][$index] =~ s/&/\\&/g; $name[$listnum][$index] =~ s/\$/\\\$/g; print "[", $oname[$listnum][$index], "]: "; $inp=; chop($inp); unless (($inp eq "") || ($inp eq " ")) { print "Naming track ", $list[$listnum][$index], " to ", $inp, "\n"; # Set $oname[][] to the name before putting in the '\'s. $oname[$listnum][$index] = $inp; # Add escapes to the appropriate characters # Replace (, ), ', ` chars with \(, \), \', \`, etc. $inp =~ s/\(/\\(/g; $inp =~ s/\)/\\)/g; $inp =~ s/'/\\'/g; $inp =~ s/`/\\`/g; $inp =~ s/\"/\\\"/g; $inp =~ s/ /\\ /g; $inp =~ s/\;/\\\;/g; $inp =~ s/,/\\,/g; $inp =~ s/&/\\&/g; $inp =~ s/\$/\\\$/g; $name[$listnum][$index] = $inp; } $index++; if ($inp eq " ") { print "Going back...\n"; $index--; $index--; if ($index == -1) { $listnum--; $index = 0; if ($listnum == -1) { $listnum = 0; } else { $index = $#{$list[$listnum]}; } } } } print "-------------------------------------------------------------------------------\n"; } # If $setlabels eq "list" set $artist[$listnum] now. if ($setlabels eq "list") { # Set the $artist now if ($askclassical eq "on") { # If this is the first time around, set $default = $artist if (($listnum < 1) && ($conductor eq "")) { $default = $artist; } else { $default = $conductor; } print "Enter conductor. If there isn't one, enter null.\n"; print " (single space = null): [", $default, "]: "; $inp = ; chop($inp); if ($inp eq "") { $conductor = $default; } else { $conductor = $inp; } if ($inp eq " ") { $conductor = ""; } if ($conductor ne "") { print "You have entered a conductor so this will be your artist's name.\n"; $artist = $conductor; } else { if (($listnum < 1) && ($performer eq "")) { $default = $artist; } else { $default = $performer; } print "Since there is no conductor, there's probably a (main) performer.\n"; print "If this is true, enter this performer (single space = null): [", $default, "]: "; $inp = ; chop($inp); if ($inp eq "") { $performer = $default; } else { $performer = $inp; } if ($inp eq " ") { $performer = ""; } if ($performer ne "") { print "You have entered a performer so this will be your artist's name.\n"; $artist = $performer; } else { if (($listnum < 1) && ($ensemble eq "")) { $default = $artist; } else { $default = $ensemble; } print "Since there is no main performer or conductor,\n"; print " the 'artist' is probably an ensemble.\n"; print "If this is true, enter the name of the ensemble (single space = null): [", $default, "]: "; $inp = ; chop($inp); if ($inp eq "") { $ensemble = $default; } else { $ensemble = $inp; } if ($inp eq " ") { $ensemble = ""; } if ($ensemble ne "") { print "You have entered an ensemble so this will be your 'artist'.\n"; $artist = $ensemble; } else { print "Okay, just enter the artist then.\n"; print "Enter artist (single space = null): [", $artist, "]: "; $inp = ; chop($inp); if ($inp ne "") { $artist = $inp; } if ($inp eq " ") { $artist = ""; } } } } } else { print "Enter artist (single space = null): [", $artist, "]: "; $inp = ; chop($inp); if ($inp ne "") { $artist = $inp; } if ($inp eq " ") { $artist = ""; } } } # Set these fields regardless if null or not # because they are all labeled per list. $conductor[$listnum] = $conductor; $performer[$listnum] = $performer; $ensemble[$listnum] = $ensemble; $artist[$listnum] = $artist; if (($listing ne "all") && ($listing ne "each")) { # Set $recdate for the tracks in this list if ($firstdate) { print "Enter the date of recording -\n"; print "\n(formatting notes: no format is specifically required, but it is definitely\n"; print " preferable to include all FOUR digits of the year, and since it'll never\n"; print " always be clear whether it's MM-DD or DD-MM, it is actually preferable\n"; print " to spell out the month (at least the first 3 letters anyway) and then the day,\n"; print " but if you really want to use a numeric format, chose the ISO-8601 standard\n"; print " (YYYY-MM-DD), however note that it may still be unclear to some which number\n"; print " is the month and which is the day. So it is recommended that you use dates\n"; print " such as \"March 24, 1994\", \"March, 1994\", or \"1994\" (depending on how much\n"; print " information you have), and if all you have is the production (P) date, put\n"; print " \"(P)1994\". The actual recording date is usually up to a year or two before\n"; print " the production date.\n"; $firstdate = 0; } print "Enter the date of recording (single space = null): ["; if ($recdate eq "") { print "don't put one"; } else { print $recdate; } print "]: "; $inp = ; chop $inp; if ($inp ne "") { $recdate = $inp; } if ($inp eq " ") { $recdate = ""; } } $recdate[$listnum] = $recdate; # If $setlabels eq "list", set other tag fields here... if ($setlabels eq "list") { print "\nType the name of a field tag that you'd like to add to\n"; print " all these music files (or make up your own field tag name).\n"; print "You can enter the fieldname then enter the data for that fieldname,\n"; print "or you can enter fieldname=data all on one line.\n"; # List some possible recommended tags print "\nPossible tag recommendations:\n"; if ($askclassical eq "on") { if ($composer eq "") { print " composer"; } if ($conductor eq "") { print " conductor"; } if ($ensemble eq "") { print " ensemble"; } print " opus\n"; } print " location performer copyright license\n\n"; # Continue print "Just press (with nothing on the line) to finish:\n"; $finished = 0; $tagindex = 0; while (!$finished) { $inp = ; chop $inp; if (($inp ne "") && ($inp ne " ") && ($inp ne ".")) { # If there's an "=" assume the line is "fieldname=data" if ($inp =~ m/=/) { $tag[$listnum][$tagindex] = $inp; } else { # There is no "=". Assume the line is just the fieldname. $tagname = $inp; print "Set " . $tagname . "="; $inp = ; chop $inp; $tagdata = $inp; $tag[$listnum][$tagindex] = $tagname . "=" . $tagdata; } $tagindex++; } else { $finished = 1; } } } $listnum++; } # If editnames is "both", here is the last chance to edit the filenames # This is basically a reiteration of the above code. if ($editnames eq "both") { print "\nHere are the filenames you put:\n"; # Create the filenames.txt file now open(NAMEFILE, ">filenames.txt"); $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { print NAMEFILE "$oname[$listnum][$index]\n"; $index++; } print NAMEFILE "\n"; $listnum++; } close(NAMEFILE); # Assume the computer-generated defaults aren't broken! $broken = 0; $warning = 0; $firstpass = 1; do { # Print out the filenames.txt file to the screen print "-------------------------------------------------------------------------------\n"; open(NAMEFILE, "filenames.txt"); while ($line = ) { # Process $line just like the filenames would be before showing them chop $line; $line =~ s/^\s*//; $line =~ s/\s*$//; print $line, "\n"; } close(NAMEFILE); # Query $default = "no"; if ($warning) { print $warningmsg; $default = "yes"; } if ($broken) { print $reason; $default = "yes"; } if ($firstpass) { $default = "yes"; } print "Edit the above filenames? [" . $default . "]: "; $inp=; chop($inp); if ($inp eq "") { $inp = $default; } $inp =~ s/\s//g; if ($inp =~ m/^\s*y/i) { system "$editor filenames.txt"; $firstpass = 0; } # Process filenames.txt into $oname[][] and $name[][] $broken = 0; # Will set this to 1 if the file is discovered to be broken $warning = 0; open(NAMEFILE, "filenames.txt"); $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { $oname[$listnum][$index] = ; chop $oname[$listnum][$index]; # Clear off any whitespace at the beginning or end of string $oname[$listnum][$index] =~ s/^\s*//; $oname[$listnum][$index] =~ s/\s*$//; # But there are any spaces left set $broken if (($oname[$listnum][$index] =~ m/\s/) && ($allowspaces ne "on")) { $broken = 1; $reason = "No spaces allowed in filenames.\n"; } unless ($oname[$listnum][$index] =~ m/\w/) { $broken = 1; $reason = "Invalid filename detected (no word characters).\n"; } if ($oname[$listnum][$index] eq "") { $broken = 1; $reason = "There must be one (and only one) empty line between each list.\n"; } if ($oname[$listnum][$index] =~ m/\.(ogg|mp3|wav)$/i) { # Not broken, but print a notice and set default to edit again. $warning = 1; $warningmsg = "Warning: You are not supposed to end your filenames with an extension here.\n"; } $name[$listnum][$index] = $oname[$listnum][$index]; # Add escapes to the appropriate characters # Replace (, ), ', ` chars with \(, \), \', \`, etc. $name[$listnum][$index] =~ s/\(/\\(/g; $name[$listnum][$index] =~ s/\)/\\)/g; $name[$listnum][$index] =~ s/'/\\'/g; $name[$listnum][$index] =~ s/`/\\`/g; $name[$listnum][$index] =~ s/\"/\\\"/g; $name[$listnum][$index] =~ s/ /\\ /g; $name[$listnum][$index] =~ s/\;/\\\;/g; $name[$listnum][$index] =~ s/,/\\,/g; $name[$listnum][$index] =~ s/&/\\&/g; $name[$listnum][$index] =~ s/\$/\\\$/g; $index++; } $emptyline = ; chop $emptyline; $emptyline =~ s/\s//g; if ($emptyline ne "") { $broken = 1; $emptyline = "not_empty"; $reason = "There cannot be empty lines within a list.\n"; } $listnum++; } # If the names do not process go thru the loop again } until (($inp eq "no") && (!$broken)); } print "\n\n"; # Note: $oname[][] (original name) is the same as $name[][] with the # exception that $name includes an escape "\" on characters used to # specify the filename from the shell. When specifying the filename # in perl (i.e. using print), use $oname[][]. When specifying the # filename in a shell (i.e. using ``), use $name[][]. # Start the .tag file for each file. $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { open(TAGFILE, ">$oname[$listnum][$index].tag"); # Set tracknumber (left-pad with zeros to two digits) $tmptrnum = $list[$listnum][$index]; if (length($tmptrnum) == 1) { if ($tmptrnum =~ /\d/) { $tmptrnum = "0" . $tmptrnum; } else { $tmptrnum = ""; } } elsif (length($tmptrnum) == 2) { unless ($tmptrnum =~ /\d\d/) { $tmptrnum = ""; } } else { $tmptrnum = ""; } # Set the title string ($titlestr) # If $settitle is "cddb" and there is CDDB info set the title to that, # otherwise set it from the filename. if (($settitle eq "cddb") && ($tocorigname[$list[$listnum][$index]] ne "")) { # Set from CDDB info $titlestr = $tocorigname[$list[$listnum][$index]]; # Now change underscores back to spaces... $titlestr =~ s/_/ /g; } else { # Set from filename (after first "_-_") $titlestr = $oname[$listnum][$index]; # Now strip off the artist name (everything before the first _-_) if ($titlestr =~ m/_-_(.+)/) { $titlestr = $1; } # Now check to see if $albumabv is in the title. if ($albumabv ne "") { if ($titlestr =~ m/^\.?$albumabv/) { $titlestr =~ s/^\.?$albumabv\.?\d?\d//; } } # Now change underscores back to spaces... $titlestr =~ s/_/ /g; # Trim off any spaces on the beginning or end $titlestr =~ s/^\s+//; $titlestr =~ s/\s+$//; # Make array of titles for possible CDDB submit $titlestr[$list[$listnum][$index]] = $titlestr; } # Tag the file if ($titlestr ne "") { print TAGFILE "title=$titlestr\n"; } # Artist info if ($artist[$listnum] ne "") { print TAGFILE "artist=$artist[$listnum]\n"; } # Composer should be mandatory for Classical, but if it's not set # it is still possible that it is being added as a user-specified tag. if ($composer ne "") { print TAGFILE "composer=$composer\n"; } # Conductor and Performer may or may not be set. If they have been set CD-wide, # then the list-specific variable is set during the list query section. if ($conductor[$listnum] ne "") { print TAGFILE "conductor=$conductor[$listnum]\n"; } if ($performer[$listnum] ne "") { print TAGFILE "performer=$performer[$listnum]\n"; } if ($ensemble[$listnum] ne "") { print TAGFILE "ensemble=$ensemble[$listnum]\n"; } # Date of recording - tends to immediately follow artist info if ($recdate[$listnum] ne "") { print TAGFILE "date=$recdate[$listnum]\n"; } # User-added tags: (presumably this is probably also artist-related) $tagindex = 0; if ($setlabels eq "list") { while ($tagindex <= $#{$tag[$listnum]}) { print TAGFILE "$tag[$listnum][$tagindex]\n"; $tagindex++; } } else { while ($tagindex <= $#tag) { print TAGFILE "$tag[$tagindex]\n"; $tagindex++; } } # Album info if ($album ne "") { print TAGFILE "album=$album\n"; } if ($label ne "") { print TAGFILE "label=$label\n"; } if ($labelno ne "") { print TAGFILE "labelno=$labelno\n"; } # Track & partnumber info print TAGFILE "tracknumber=$tmptrnum\n"; # The partnumber is just which place it is in its list. if ($#{$name[$listnum]} > 1) { $partnumber = $index + 1; print TAGFILE "partnumber=$partnumber\n"; } if ($genre ne "") { print TAGFILE "genre=$genre\n"; } # Additional stuff if ($contact ne "") { print TAGFILE "contact=$contact\n"; } close(TAGFILE); # Done creating the tag file for this particular file # Now print the track - filename, and the tag file. print $tmptrnum . ": " . $oname[$listnum][$index] . "\n"; $out=`cat -- $name[$listnum][$index].tag`; print $out, "\n"; $index++; } print "\n"; $listnum++; } # Prompt to see if user wants to edit any of the .tag files print "\nLook at the above tags and make sure they are all okay.\n"; print "You can edit any of these tag files by entering the track number.\n"; print "You can also enter \"submit\" to submit this data to the freedb\n"; print "CDDB database or just press by itself to go directly to\n"; print "the ripping process! (or press ctrl-C to abort everything).\n"; do { print "Enter track number, submit, or just press to Rip! : "; $inp = ; chop $inp; if (($inp eq " ") || ($inp eq ".")) { $inp = ""; } if ($inp =~ m/\d+/) { $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { if ($inp == $list[$listnum][$index]) { system "$editor $name[$listnum][$index].tag"; } $index++; } $listnum++; } } } until (($inp eq "") || ($inp =~ m/submit/i)); # Submit to the freedb CDDB database if desired. if ($inp =~ m/submit/i) { # First make sure $genre is one of the 11 freedb categories $cgy = $genre; while (($cgy ne "classical") && ($cgy ne "blues") && ($cgy ne "country") && ($cgy ne "data") && ($cgy ne "folk") && ($cgy ne "jazz") && ($cgy ne "newage") && ($cgy ne "reggae") && ($cgy ne "rock") && ($cgy ne "soundtrack") && ($cgy ne "misc")) { print "\nThe genre you've selected (\"$cgy\") is not a category that\n"; print "freedb accepts.\n"; print "Please enter one of the following categories for submission:\n"; print " classical blues country data folk jazz newage\n"; print " reggae rock soundtrack misc\n> "; $cgy = ; chop $cgy; if ($cgy eq "data") { print "\"data\"?! Are you sure? [no]: "; $inp = ; chop $inp; unless ($inp =~ m/y/i) { $cgy = ""; } } } # Write the original raw CDDB info pulled from freedb $cddborig = "$cddbsubmitdir/cddb_orig_$discid"; open(CDDBOR, ">$cddborig"); foreach $tmp (@{cd->{raw}}) { # Now's the chance to pull the revision number if ($tmp =~ m/^#\s+Revision:\s*(\d+)/) { $revision = $1 + 1; } print CDDBOR $tmp; } close(CDDBOR); # Now create and write submission to file to be e-mailed $cddbfile = "$cddbsubmitdir/cddb_submit_$discid"; open(CDDBFD, ">$cddbfile"); print CDDBFD "# xmcd CD database file\n#\n# Track frame offsets:\n"; foreach $tmp (0 .. ($totaltracks - 1)) { print CDDBFD "# ", $toc->[$tmp]{frames}, "\n"; } $cddbduration = int($toc->[$totaltracks]{frames} / 75); print CDDBFD "#\n# Disc length: ", $cddbduration, " seconds\n#\n"; print CDDBFD "# Revision: ", $revision, "\n"; print CDDBFD "# Submitted via: ", $version, "\n#\n"; # End of header print CDDBFD "DISCID=$discid\n"; if (($cgy eq "classical") && ($composer ne "")) { print CDDBFD "DTITLE=$composer / $album\n"; } else { if (($artist ne "") && ($album ne "")) { print CDDBFD "DTITLE=$artist / $album\n"; } elsif ($artist ne "") { print CDDBFD "DTITLE=$artist\n"; } elsif ($album ne "") { print CDDBFD "DTITLE=$album\n"; } else { # hmmm... this really shouldn't happen print "WARNING: Both artist and album are NOT SET.\n"; print CDDBFD "DTITLE=\n"; } } $recdate[0] =~ m/(\d\d\d\d)/; $year = $1; print CDDBFD "DYEAR=$year\n"; print CDDBFD "DGENRE=$cgy\n"; foreach $tnm (1 .. $totaltracks) { $tmp = $tnm - 1; print CDDBFD "TTITLE$tmp=$titlestr[$tnm]\n"; } # Write EXTD and EXTT info if ($setlabels eq "list") { print CDDBFD "EXTD=\n"; foreach $tnm (1 .. $totaltracks) { $tmp = $tnm - 1; # Find $listnum that track $tnm is in. $listnum = 0; $index = -1; do { $index++; if ($index > $#{$list[$listnum]}) { $index = 0; $listnum++; } if ($listnum > $#list) { # This should never happen print "WTF? Track $tnm isn't in any list!\n"; break; } } until ($tnm == $list[$listnum][$index]); # Now write all user-specified tag info to each EXTT# # (hey, you gotta better idea?) $tagindex = 0; while ($tagindex <= $#{$tag[$listnum]}) { print CDDBFD "EXTT$tmp=$tag[$listnum][$tagindex]\n"; $tagindex++; } if ($tagindex == 0) { print CDDBFD "EXTT$tmp=\n"; } } } else { $tagindex = 0; while ($tagindex <= $#tag) { print CDDBFD "EXTD=$tag[$tagindex]\n"; $tagindex++; } if ($tagindex == 0) { print CDDBFD "EXTD=\n"; } foreach $tnm (1 .. $totaltracks) { $tmp = $tnm - 1; print CDDBFD "EXTT$tmp=\n"; } } # End of EXTD and EXTT section print CDDBFD "PLAYORDER=\n"; close(CDDBFD); # Verify with the user that the file is correct. do { # Print out original raw CDDB info print "\nORIGINAL CDDB RECORD:\n"; $out = `cat -- $cddborig`; print $out; # Print out the new CDDB submission data print "\nYOUR NEW SUBMISSION:\n"; $out = `cat -- $cddbfile`; print $out; print "\nPlease be absolutely sure that the above information is correct\n"; print "and better than the original CDDB record before submitting it to\n"; print "the CDDB database!"; print "\nDoes it look good? (accept/edit/abort) [edit]: "; $inp = ; chop $inp; if (($inp eq "") || ($inp =~ m/edit/i)) { system "$editor $cddbfile"; } } until (($inp =~ m/accept/i) || ($inp =~ m/abort/i)); # Finally, mail off the file if ($inp =~ m/abort/i) { print "Aborted.\n\n"; } else { print "\nmailing $cddbfile to $cddbsubmitaddr... "; `mail -a "Content-Type: text/plain; charset=\"$charset\"" -a "Content-Transfer-Encoding: 8bit" -s "cddb $cgy $discid" -c $cddbsubmitaddrCc $cddbsubmitaddr < $cddbfile`; print "Done.\n\n"; } } # Now rip all of the tracks in each list # cdparanoia command: print "\n\nBeginning the rip...\n\n"; print "NOTE: You may press ctrl-C during the ripping process to abort\n"; print " the current rip and get the opportunity to rip with different\n"; print " cdparanoia command-line parameters.\n\n"; # Maintain a list of tracks that are possible flawed # (aborted and rerun without the "-z") $posflawed = ""; $listnum = 0; while ($listnum <= $#list) { $index = 0; while ($index <= $#{$list[$listnum]}) { if ($skiprip eq "on") { print "Creating empty file: $oname[$listnum][$index].wav\n"; `cat /dev/null > $name[$listnum][$index].wav`; } else { $tmpcdflags = $cdparanoiaflags; $trackaborted = 0; do { print "\n---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----\n"; print "Ripping track ", $list[$listnum][$index], "...\n\n"; $cdpcmd="cdparanoia $tmpcdflags -d $cddevice $list[$listnum][$index]"; print "Command: $cdpcmd\n"; $cdpout = system "$cdpcmd"; if ($cdpout != 0) { $trackaborted = 1; print "\n\nAborted.\n\n"; print "Retry this track with different cdparanoia flags? (y/n) [y]: "; $inp = ; chop $inp; if ($inp =~ m/^\s*n/i) { # If answer is no... # Just continue out of the loop. $cdpout = 0; } else { # Presumably answer is yes... this is the safe path anyway. print "\nThe old cdparanoia flags are \"", $tmpcdflags, "\".\n"; # If unchanged, offer suggestions if ($tmpcdflags eq $cdparanoiaflags) { print "Suggestions:\n -v -z\n -v -z -S 1\n -v -Z -S 1\n"; } print "Enter the new flags to try for this track: [", $tmpcdflags, "]: "; $inp = ; chop $inp; if ($inp ne "") { $tmpcdflags = $inp; } # unless (($tmpcdflags =~ m/\b-z\b/) || ($trackposflawed)) { # The \b-z\b part didn't work # # Track was aborted and reripped without the "-z" flag. Take note. # $posflawed = $posflawed . " " . $list[$listnum][$index]; # $posflawed = $posflawed . " - " . $oname[$listnum][$index] . "\n"; # $trackposflawed = 1; # Only take note once though. # } } } else { # Track successfully finished ripping # But if $tmpcdflags didn't have the '-z' flag in it then give a warning. if ($cdparanoiaflags =~ m/-z/) { unless ($tmpcdflags =~ m/-z/) { $posflawed = $posflawed . " " . $list[$listnum][$index]; $posflawed = $posflawed . " - " . $oname[$listnum][$index] . "\n"; } } } } until ($cdpout == 0); # It would be nice to be able to get status/return codes from cdparanoia # to determine whether or not the rip is hanging, there's a skip ("V") in # the rip, or it otherwise failed or aborted WITHOUT having to get ctrl-C # signals from the user. But until someone implements that in cdparanoia # I guess we'll just have to live with this glaring design flaw in cdparanoia. # I'd very-much like to implement something like this: # } else { # print "\n\n\n --- An Error Occurred in the ripping! ---\n\n\n"; # } # ...but there is currently no way to do it! # Rename cdda.wav to $name[][].wav print "Moving cdda.wav to $name[$listnum][$index].wav\n"; `mv -- cdda.wav $name[$listnum][$index].wav`; } # End if ($skiprip eq "on) $index++; } $listnum++; print "\n"; } print "Finished ripping.\n"; print "For the rest of this process crip will not need the CD.\n\n\n"; # Some of us will change CDs now and immediately start another instance # of crip to rip another CD while this one is processing and encoding. # I personally wait until the encoding starts so that all the major # disk/IO is over with though. # Eject CD if that option is turned on. if ($ejectcd eq "on") { print "Attempting to eject CD...\n"; $ejectcmd = "eject " . $cddevice; print "Running `$ejectcmd`\n"; `$ejectcmd`; print "\n"; } # Now's the time for a stop-gap prompt (i.e. if a user wants the chance # to edit the raw .wav files before the processing begins)... if ($stopgap eq "on") { # The following line is just a stop-gap if needed. print "Ripping complete.\n"; print "You may now edit the raw .wav files or whatever...\n"; print "\nPress when ready to continue processing: "; $inp = ; print "\n"; } # Normalization and Trimming processing section # If normalizing, compute the $voladjust value for the list, which # will be based off the list's highest peak-value. if ($normalize eq "on") { print "Volume threshold is ", $volthresh, ".\n"; } else { print "Will not normalize.\n"; } $listnum = 0; while ($listnum <= $#list) { # Figure out what $volarg should be $volarg = ""; if ($normalize eq "on") { print "\n\nFinding peak volume for list ", $listnum, "\n"; $index = 0; $voladjust = 999999; while ($index <= $#{$list[$listnum]}) { # && ($voladjust >= $volthresh)) { # We want to get all the peaks anyway... $statout=`sox $name[$listnum][$index].wav -e stat -v 2>&1`; chop($statout); print "Volume adjust for ", $oname[$listnum][$index], ".wav: ", $statout, "\n"; $origpeak[$list[$listnum][$index]] = 1.0 / $statout; if ($statout < $voladjust) { $voladjust = $statout; } $index++; } # Set the volume adjust argument for sox (or leave null) if ($voladjust >= $volthresh) { # Add a volume adjust argument to sox. print "\n\nAdjusting volume of list ", $listnum, " to ", $voladjust, "\n"; $normval[$listnum] = $voladjust; $volarg = "vol " . $voladjust; } else { print "\n\nNot adjusting volume of list ", $listnum, " to ", $voladjust, " (not worth it)\n"; $normval[$listnum] = ""; } } # Takes out any beginning or ending quiet time # (only take out quiet time if it's at the beginning or end of a group) # also normalize (if necessary) at the same time # Name of tracks should go from $name[][].wav to $name[][] $index = 0; while ($index <= $#{$list[$listnum]}) { $trimarg = ""; if ($trimsilence eq "on") { $trimarg = $trimsilargs; } $soxcmd1 = ""; $soxcmd2 = ""; # Set up the sox command(s): if ($trimsilence eq "on") { # Case 1: track is the only track in list. # Trim both beginning and end of file: if (($index == 0) && ($#{$list[$listnum]} == 0)) { $soxcmd1 = "sox $name[$listnum][$index].orig.wav -t wav $name[$listnum][$index].rev.wav $trimarg $volarg reverse"; $soxcmd2 = "sox $name[$listnum][$index].rev.wav -t wav $name[$listnum][$index].wav $trimarg reverse"; } # Case 2: track is the 1st track of a group in list # Trim only the beginning of the file: if (($index == 0) && ($#{$list[$listnum]} > 0)) { $soxcmd1 = "sox $name[$listnum][$index].orig.wav -t wav $name[$listnum][$index].wav $trimarg $volarg"; } # Case 3: track is the last track of a group in list # Trim only the end of the file: if (($index == $#{$list[$listnum]}) && ($index > 0)) { $soxcmd1 = "sox $name[$listnum][$index].orig.wav -t wav $name[$listnum][$index].rev.wav $volarg reverse"; $soxcmd2 = "sox $name[$listnum][$index].rev.wav -t wav $name[$listnum][$index].wav $trimarg reverse"; } # Case 4: track is in the middle somewhere of a group in list # Do not trim at all if (($index > 0) && ($index < $#{$list[$listnum]})) { if ($volarg ne "") { # Still have to normalize... $soxcmd1 = "sox $name[$listnum][$index].orig.wav -t wav $name[$listnum][$index].wav $volarg"; } else { print "Leaving $oname[$listnum][$index].wav alone."; print " (not trimming nor normalizing)\n"; } } } else { # Silence trimming is off: if ($volarg ne "") { # Set the sox command to only do normalization: $soxcmd1 = "sox $name[$listnum][$index].orig.wav -t wav $name[$listnum][$index].wav $volarg"; } else { # Trimming off & no volargs... print "Leaving $oname[$listnum][$index].wav alone."; print " (not trimming nor normalizing)\n"; } } # Now actually run the sox command(s): if ($soxcmd1 ne "") { # First move ripped file to .wav.orig: print "Moving $oname[$listnum][$index].wav to $oname[$listnum][$index].orig.wav\n"; `mv -- $name[$listnum][$index].wav $name[$listnum][$index].orig.wav`; print "Running sox command:\n $soxcmd1\n"; `$soxcmd1`; # Simple enough not to fail if there's no $soxcmd2 if ($soxcmd2 ne "") { unless (-e $oname[$listnum][$index] . ".rev.wav") { # $soxcmd1 apparently failed and file does not exist! print "$name[$listnum][$index].rev.wav was not created. (sox bug?)\n"; print "Attempting work-around...\n"; # Rerun $soxcmd1 but try commands one at a time... $soxcmd1a = substr($soxcmd1, 0, length($soxcmd1) - 8); # take off the "reverse" print "Trying sox command:\n $soxcmd1a\n"; `$soxcmd1a`; print "Moving $name[$listnum][$index].rev.wav to $name[$listnum][$index].sil.wav\n"; `mv $name[$listnum][$index].rev.wav $name[$listnum][$index].sil.wav`; $soxcmd1b = "sox $name[$listnum][$index].sil.wav -t wav $name[$listnum][$index].rev.wav reverse"; print "Now running sox command:\n $soxcmd1b\n"; `$soxcmd1b`; unless (-e $oname[$listnum][$index] . ".rev.wav") { # Damn. Now what?! print "sox cmd1 failed... Giving up on this track.\n"; print "Press to continue: "; $inp = ; } } print "Running sox command:\n $soxcmd2\n"; `$soxcmd2`; unless (-e $oname[$listnum][$index] . ".wav") { # soxcmd2 apparently failed and file does not exist! print "$name[$listnum][$index].wav was not created. (sox bug?)\n"; print "Attempting work-around...\n"; # Rerun $soxcmd2 but try commands one at a time... $soxcmd2a = substr($soxcmd2, 0, length($soxcmd2) - 8); # minus the "reverse" print "Trying sox command:\n $soxcmd2a\n"; `$soxcmd2a`; print "Moving $name[$listnum][$index].wav to $name[$listnum][$index].sil.wav\n"; `mv $name[$listnum][$index].wav $name[$listnum][$index].sil.wav`; $soxcmd2b = "sox $name[$listnum][$index].sil.wav -t wav $name[$listnum][$index].wav reverse"; print "Now running sox command:\n $soxcmd2b\n"; `$soxcmd2b`; unless (-e $oname[$listnum][$index] . ".wav") { # Actually this shouldn't happen... print "sox cmd2 failed... Giving up on this track.\n"; print "Press to continue: "; $inp = ; } } } } $index++; } $listnum++; print "\n"; } # End while ($listnum <= $#list) # Encoding section if ($encodeto eq "vorbis") { $encodestr = "oggenc " . $oggencflags; } else { $encodestr = "flac " . $flacflags; } print "\nEncoding with: ", $encodestr, "\n"; $listnum = 0; while ($listnum <= $#list) { # With flac, must encode the whole list on one command line so that # the replaygain option (if there) gets all the files in the same 'album'. if ($encodeto eq "flac") { # Build a filelist and encode them all at once $index = 0; $filelist = ""; while ($index <= $#{$list[$listnum]}) { $filelist = $filelist . $name[$listnum][$index] . ".wav "; $index++; } # Now encode the whole filelist print "\nEncoding list $listnum:\n$encodestr $filelist\n\n"; `$encodestr $filelist`; } $index = 0; while ($index <= $#{$list[$listnum]}) { # Encode (if flac, encoding already done) unless ($encodeto eq "flac") { print "\nEncoding ", $oname[$listnum][$index], ".wav\n"; `$encodestr $name[$listnum][$index].wav`; } # Tag # Set the final comment string ($commentstr) $commentstr = ""; # I used to have DiscID-track in the comment field (from the days when # I used to make MP3s) but now it's more appropriate the have them in # their separate Ogg tags. So I commented out the next two lines: #if ($tmptrnum eq "") { $commentstr = $discid . " "; } #else { $commentstr = $discid . "-" . $tmptrnum . " "; } if ($normalize eq "on") { if ($normval[$listnum] eq "") { $peak = $origpeak[$list[$listnum][$index]]; # Convert $peak to X.XXX format $peak = $peak + "0.0004999999"; $peak = substr($peak, 0, 5); $commentstr = $commentstr . "not normalized, "; $commentstr = $commentstr . "peak=" . $peak . ", "; } else { $newpeak = $origpeak[$list[$listnum][$index]] * $normval[$listnum]; # Convert $newpeak to X.XXX format $newpeak = $newpeak + "0.0004999999"; $newpeak = substr($newpeak, 0, 5); $commentstr = $commentstr . "normalized x" . $normval[$listnum] . ", "; $commentstr = $commentstr . "new peak=" . $newpeak . ", "; } } $commentstr = $commentstr . $comment0; $timestamp = `date`; chop $timestamp; $commentstr = $commentstr . $timestamp; open(TAGFILE, ">>$oname[$listnum][$index].tag"); print TAGFILE "comment=$commentstr\n"; if ($comment ne "") { print TAGFILE "comment=$comment\n"; } print TAGFILE "sourcemedia=$sourcemedia\n"; print TAGFILE "discid=$discid\n"; print TAGFILE "encoding=$encoding\n"; close(TAGFILE); # Okay finally, print what the .tag file finally looks like, # and then tag the file with the .tag file if ($encodeto eq "vorbis") { print "Tagging $oname[$listnum][$index].ogg:\n"; $out=`cat -- $name[$listnum][$index].tag`; print $out, "\n"; `vorbiscomment -w -c $name[$listnum][$index].tag $name[$listnum][$index].ogg`; } else { if ($flacflags =~ m/--ogg/i) { print "Tagging $oname[$listnum][$index].ogg:\n"; $out=`cat -- $name[$listnum][$index].tag`; print $out, "\n"; if ($mfver lt "1.1.1") { $mfcmd = "metaflac --import-vc-from=$name[$listnum][$index].tag $name[$listnum][$index].ogg"; } else { $mfcmd = "metaflac --import-tags-from=$name[$listnum][$index].tag $name[$listnum][$index].ogg"; } print "Executing:\n$mfcmd\n"; `$mfcmd`; } else { print "Tagging $oname[$listnum][$index].flac:\n"; $out=`cat -- $name[$listnum][$index].tag`; print $out, "\n"; if ($mfver lt "1.1.1") { $mfcmd = "metaflac --import-vc-from=$name[$listnum][$index].tag $name[$listnum][$index].flac"; } else { $mfcmd = "metaflac --import-tags-from=$name[$listnum][$index].tag $name[$listnum][$index].flac"; } print "Executing:\n$mfcmd\n"; `$mfcmd`; } } # Delete the tag file (if $delfiles is "on") if ($delfiles eq "on") { # Delete .wav file(s) print "\nDeleting ", $oname[$listnum][$index], ".wav\n"; `rm -- $name[$listnum][$index].wav`; $tmpfilename = $oname[$listnum][$index] . ".orig.wav"; if (-e $tmpfilename) { print "Deleting $tmpfilename\n"; `rm -- $name[$listnum][$index].orig.wav`; } $tmpfilename = $oname[$listnum][$index] . ".rev.wav"; if (-e $tmpfilename) { print "Deleting $tmpfilename\n"; `rm -- $name[$listnum][$index].rev.wav`; } $tmpfilename = $oname[$listnum][$index] . ".sil.wav"; if (-e $tmpfilename) { print "Deleting $tmpfilename\n"; `rm -- $name[$listnum][$index].sil.wav`; } # Delete .tag file print "Deleting $oname[$listnum][$index].tag\n"; `rm -- $name[$listnum][$index].tag`; if (-e "$oname[$listnum][$index].tag~") { print "Deleting $oname[$listnum][$index].tag~\n"; `rm -- $name[$listnum][$index].tag~`; } } print "Done.\n\n"; $index++; } # Add replaygain tags. # If normalize is on, don't bother with replaygain # (only for non-flac files, which were done during the encode) if (($normalize eq "off") && ($encodeto eq "vorbis")) { # Now run replaygain (vorbisgain) on all the tracks in the list. # First build the list of files in the list. $index = 0; $filelist = ""; while ($index <= $#{$list[$listnum]}) { $filelist = $filelist . $name[$listnum][$index] . ".ogg "; $index++; } # If there is more than one track in the list, run in album mode if ($index > 1) { print "Running vorbisgain on group ", $listnum, "...\n"; `vorbisgain -a -- $filelist`; } else { print "Running vorbisgain on track ", $filelist, "...\n"; `vorbisgain -- $filelist`; } } # Increment the list and go on... $listnum++; print "\n\n"; } # Delete the filenames.txt file if ($delfiles eq "on") { print "Deleting filenames.txt\n"; `rm filenames.txt`; if (-e "filenames.txt~") { print "Deleting filenames.txt~\n"; `rm filenames.txt~`; } } # Before printing "Done!" list the $posflawed tracks. if ($posflawed ne "") { print "\n\n"; print "REMINDER: The following tracks were aborted and re-ripped\n"; print "without the \"-z\" option (and could be flawed):\n\n"; print $posflawed; print "\nSo listen to them just to make sure...\n"; } # Wait for user to hit , then either end or start all over again... print "Done!\n"; #print " Change CDs and hit .\n"; #print " Ctrl-C to quit...\n\n> "; #$inp = ; # To change the behavior so that the script restarts from the beginning, # uncomment the next line and comment out the "exit;" below. #reset; # Just exit for now... exit; } # End of script crip-3.9/LICENSE0000644000000000000000000000101007623434265012030 0ustar rootrootLICENSE agreement for crip -------------------------- crip is GPL. It was written in the spirit of open source and its implications. If you make an improvement, find a bug, or have a comment, please e-mail me at charlton@dynet.com. If you are using this software for commercial purposes, I would be interested to know what your organization is and what you are doing with the software. You can contact me at charlton@dynet.com. I'm also available for consulting purposes. Charlton Harrison charlton@dynet.com crip-3.9/README0000644000000000000000000000412210560326242011677 0ustar rootrootREADME for crip - last updated: Sat May 7 04:10:30 CDT 2005 ------------------------------------------------------------------------------- INSTALL INSTRUCTIONS: --------------------- This should help get you started: You will need the following software installed first: Linux, perl, cdparanoia, oggenc (Ogg Vorbis encoder) or FLAC (Free Lossless Audio Codec encoder), vorbiscomment (from vorbistools) (if encoding to Ogg Vorbis), vorbisgain (if you have normalization turned off as recommended), and sox (if you want to turn normalization on or trim silence (v12.17.4 or above necessary for silence trimming)). Sorry about all the prerequisites, but you should have all these on your Linux system anyway, especially if you're going to be making good, professional-quality music files. First, copy the CDDB_get.pm file somewhere where your perl will look for its .pm files like so: cp CDDB_get.pm /usr/lib/perl5/site_perl/ Copy the criprc_example file to your home directory and name it .criprc: cp criprc_example ~/.criprc Look at the variables in the .criprc file and set them the way you want them to be. Note that I use '-q 5' as the oggenc flags that I use to encode, which encodes to about 160kbps Ogg Vorbis. If you don't like it change it! USAGE INSTRUCTIONS: ------------------- Just `cd` to a directory on a robust drive with plenty of space. There will be a lot of hard drive activity so make sure the drive is good and can handle it without overheating or otherwise failing. Then run crip from the directory where you want the .wav files and .ogg / .flac files to go. crip assumes that your CDROM device is /dev/cdrom. When finished just move off the music files to where you want them to go and 'rm *' everything left in that directory. That's it! You now have very good "professional-grade" and properly labeled Ogg Vorbis (or FLAC) files of your music. For a tutorial of how to answer the questions once you run the script, plus documentation for the script, see: http://bach.dynet.com/crip/tutorial-2.5.html (I know I need to make a new tutorial). Charlton charlton@dynet.com crip-3.9/editcomment0000755000000000000000000000462210702505123013255 0ustar rootroot#!/usr/bin/perl # Written to suppliment crip with a tag editor. # Supports both .ogg and .flac files. # Put preferred editor here $editor = "vim"; $file = $ARGV[0]; unless (-e "$file") { die "File \"$file\" does not exist.\n"; } if (-e "$file.tag.tmp") { die "WTF is \"$file.tag.tmp\" already doing in /tmp ?!\n"; } # Escape certain characters from $file # code taken directly from crip actually (crip does the same # sort of thing 3 different times in its code) # (don't ask me why it worked above but doesn't work below without escapes) $file =~ s/\(/\\(/g; $file =~ s/\)/\\)/g; $file =~ s/'/\\'/g; $file =~ s/`/\\`/g; $file =~ s/\"/\\\"/g; $file =~ s/ /\\ /g; $file =~ s/\;/\\\;/g; $file =~ s/,/\\,/g; $file =~ s/&/\\&/g; $file =~ s/\$/\\\$/g; if ($file =~ m/\.ogg$/) { # First check for vorbiscomment existence: $out = `which vorbiscomment`; if ($out eq "") { die "Cannot find `vorbiscomment` for tagging the Ogg Vorbis files!\n"; } system "vorbiscomment -l $file > /tmp/$file.tag.tmp"; system "$editor /tmp/$file.tag.tmp"; print "Writing new tag info...\n"; system "vorbiscomment -w -c /tmp/$file.tag.tmp $file"; print "Done.\n"; print "Deleting temporary file /tmp/$file.tag.tmp\n"; system "rm /tmp/$file.tag.tmp"; print "\nTag info now reads:\n"; system "vorbiscomment -l $file"; } elsif ($file =~ m/\.flac$/) { # First check for metaflac existence: $out = `which metaflac`; if ($out eq "") { die "Cannot find `metaflac` for tagging the flac files!\n"; } else { # metaflac exists, get its version number $mfver = `metaflac --version`; chop $mfver; $mfver =~ m/(\d+\..+)/; $mfver = $1; } if ($mfver lt "1.1.1") { system "metaflac --export-vc-to=/tmp/$file.tag.tmp $file"; } else { system "metaflac --export-tags-to=/tmp/$file.tag.tmp $file"; } system "$editor /tmp/$file.tag.tmp"; print "Writing new tag info...\n"; if ($mfver lt "1.1.1") { system "metaflac --remove-vc-all --import-vc-from=/tmp/$file.tag.tmp $file"; } else { system "metaflac --remove-all-tags --import-tags-from=/tmp/$file.tag.tmp $file"; } print "Done.\n"; print "Deleting temporary file /tmp/$file.tag.tmp\n"; system "rm /tmp/$file.tag.tmp"; print "\nTag info now reads:\n"; if ($mfver lt "1.1.1") { system "metaflac --export-vc-to=- $file"; } else { system "metaflac --export-tags-to=- $file"; } } else { die "File \"$file\" does not have the .ogg or .flac extension.\n"; } print "\n"; crip-3.9/CDDB_get.pm0000444000000000000000000003767310702337216012730 0ustar rootroot# # CDDB - Read the CDDB entry for an audio CD in your drive # # This module/script gets the CDDB info for an audio cd. You need # LINUX, a cdrom drive and an active internet connection in order # to do that. # # (c) 2004 Armin Obersteiner # # LICENSE # # This library is released under the same conditions as Perl, that # is, either of the following: # # a) the GNU General Public License Version 2 as published by the # Free Software Foundation, # # b) the Artistic License. # package CDDB_get; use Config; use strict; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $debug); require Exporter; @ISA = qw(Exporter AutoLoader); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. @EXPORT_OK = qw( get_cddb get_discids ); $VERSION = '2.27'; use Fcntl; use IO::Socket; use Data::Dumper qw(Dumper); #$debug=1; # setup for linux, solaris x86, solaris spark # you freebsd guys give me input print STDERR "cddb: checking for os ... " if $debug; my $os=`uname -s`; my $machine=`uname -m`; chomp $os; chomp $machine; print STDERR "$os ($machine) " if $debug; # cdrom IOCTL magic (from c headers) # linux x86 is default # /usr/include/linux/cdrom.h my $CDROMREADTOCHDR=0x5305; my $CDROMREADTOCENTRY=0x5306; my $CDROM_MSF=0x02; # default config my $CDDB_HOST = "freedb.freedb.org"; my $CDDB_PORT = 8880; my $CDDB_MODE = "cddb"; my $CD_DEVICE = "/dev/cdrom"; my $HELLO_ID = "root nowhere.com fastrip 0.77"; my $PROTO_VERSION = 5; # endian check my $BIG_ENDIAN = unpack("h*", pack("s", 1)) =~ /01/; if($BIG_ENDIAN) { print STDERR "[big endian] " if $debug; } else { print STDERR "[little endian] " if $debug; } # 64bit pointer check my $BITS_64 = $Config{ptrsize} == 8 ? 1 : 0; if($BITS_64) { print STDERR "[64 bit]\n" if $debug; } else { print STDERR "[32 bit]\n" if $debug; } if($os eq "SunOS") { # /usr/include/sys/cdio.h $CDROMREADTOCHDR=0x49b; # 1179 $CDROMREADTOCENTRY=0x49c; # 1180 if(-e "/vol/dev/aliases/cdrom0") { $CD_DEVICE="/vol/dev/aliases/cdrom0"; } else { if($machine =~ /^sun/) { # on sparc and old suns $CD_DEVICE="/dev/rdsk/c0t6d0s0"; } else { # on intel $CD_DEVICE="/dev/rdsk/c1t0d0p0"; } } } elsif($os =~ /BSD/i) { # works for netbsd, infos for other bsds welcome # /usr/include/sys/cdio.h $CDROMREADTOCHDR=0x40046304; $CDROMREADTOCENTRY=0xc0086305; if($BITS_64) { $CDROMREADTOCENTRY=0xc0106305; } $CD_DEVICE="/dev/cd0a"; if($os eq "OpenBSD") { $CD_DEVICE="/dev/cd0c"; } } sub read_toc { my $device=shift; my $tochdr=chr(0) x 16; sysopen (CD,$device, O_RDONLY | O_NONBLOCK) or die "cannot open cdrom [$!] [$device]"; ioctl(CD, $CDROMREADTOCHDR, $tochdr) or die "cannot read toc [$!] [$device]"; my ($start,$end); if($os =~ /BSD/) { ($start,$end)=unpack "CC",(substr $tochdr,2,2); } else { ($start,$end)=unpack "CC",$tochdr; } print STDERR "start track: $start, end track: $end\n" if $debug; my @tracks=(); for (my $i=$start; $i<=$end;$i++) { push @tracks,$i; } push @tracks,0xAA; my @r=(); my $tocentry; my $toc=""; my $size=0; for(@tracks) { $toc.=" "; $size+=8; } if($os =~ /BSD/) { my $size_hi=int($size / 256); my $size_lo=$size & 255; if($BIG_ENDIAN) { if($BITS_64) { # better but just perl >= 5.8.0 # $tocentry=pack "CCCCx![P]P", $CDROM_MSF,0,$size_hi,$size_lo,$toc; $tocentry=pack "CCCCxxxxP", $CDROM_MSF,0,$size_hi,$size_lo,$toc; } else { $tocentry=pack "CCCCP8l", $CDROM_MSF,0,$size_hi,$size_lo,$toc; } } else { if($BITS_64) { $tocentry=pack "CCCCxxxxP", $CDROM_MSF,0,$size_lo,$size_hi,$toc; } else { $tocentry=pack "CCCCP8l", $CDROM_MSF,0,$size_lo,$size_hi,$toc; } } ioctl(CD, $CDROMREADTOCENTRY, $tocentry) or die "cannot read track info [$!] [$device]"; } my $count=0; foreach my $i (@tracks) { my ($min,$sec,$frame); unless($os =~ /BSD/) { $tocentry=pack "CCC", $i,0,$CDROM_MSF; $tocentry.=chr(0) x 16; ioctl(CD, $CDROMREADTOCENTRY, $tocentry) or die "cannot read track $i info [$!] [$device]"; ($min,$sec,$frame)=unpack "CCCC", substr($tocentry,4,4); } else { ($min,$sec,$frame)=unpack "CCC", substr($toc,$count+5,3); } $count+=8; my %cdtoc=(); $cdtoc{min}=$min; $cdtoc{sec}=$sec; $cdtoc{frame}=$frame; $cdtoc{frames}=int($frame+$sec*75+$min*60*75); my $data = unpack("C",substr($tocentry,1,1)); $cdtoc{data} = 0; if($data & 0x40) { $cdtoc{data} = 1; } push @r,\%cdtoc; } close(CD); return @r; } sub cddb_sum { my $n=shift; my $ret=0; while ($n > 0) { $ret += ($n % 10); $n = int $n / 10; } return $ret; } sub cddb_discid { my $total=shift; my $toc=shift; my $i=0; my $t=0; my $n=0; while ($i < $total) { $n = $n + cddb_sum(($toc->[$i]->{min} * 60) + $toc->[$i]->{sec}); $i++; } $t = (($toc->[$total]->{min} * 60) + $toc->[$total]->{sec}) - (($toc->[0]->{min} * 60) + $toc->[0]->{sec}); return (($n % 0xff) << 24 | $t << 8 | $total); } sub get_discids { my $cd=shift; $CD_DEVICE = $cd if (defined($cd)); my @toc=read_toc($CD_DEVICE); my $total=$#toc; my $id=cddb_discid($total,\@toc); return [$id,$total,\@toc]; } sub get_cddb { my $config=shift; my $diskid=shift; my $id; my $toc; my $total; my @r; my $input = $config->{input}; my $multi = $config->{multi}; $input = 0 if $multi; print STDERR Dumper($config) if $debug; $CDDB_HOST = $config->{CDDB_HOST} if (defined($config->{CDDB_HOST})); $CDDB_PORT = $config->{CDDB_PORT} if (defined($config->{CDDB_PORT})); $CDDB_MODE = $config->{CDDB_MODE} if (defined($config->{CDDB_MODE})); $CD_DEVICE = $config->{CD_DEVICE} if (defined($config->{CD_DEVICE})); $HELLO_ID = $config->{HELLO_ID} if (defined($config->{HELLO_ID})); $PROTO_VERSION = $config->{PROTO_VERSION} if (defined($config->{PROTO_VERSION})); my $HTTP_PROXY = $config->{HTTP_PROXY} if (defined($config->{HTTP_PROXY})); my $FW=1 if (defined($config->{FW})); if(defined($diskid)) { $id=$diskid->[0]; $total=$diskid->[1]; $toc=$diskid->[2]; } else { my $diskid=get_discids($CD_DEVICE); $id=$diskid->[0]; $total=$diskid->[1]; $toc=$diskid->[2]; } my @list=(); my $return; my $socket; my $id2 = sprintf "%08x", $id; my $query = "cddb query $id2 $total"; for (my $i=0; $i<$total ;$i++) { $query.=" $toc->[$i]->{frames}"; } # this was to old total calculation, does not work too well, its included if new version makes problems # $query.=" ". int(($toc->[$total]->{frames}-$toc->[0]->{frames})/75); $query.=" ". int(($toc->[$total]->{frames})/75); print Dumper($toc) if $debug; if ($CDDB_MODE eq "cddb") { print STDERR "cddb: connecting to $CDDB_HOST:$CDDB_PORT\n" if $debug; $socket=IO::Socket::INET->new(PeerAddr=>$CDDB_HOST, PeerPort=>$CDDB_PORT, Proto=>"tcp",Type=>SOCK_STREAM) or die "cannot connect to cddb db: $CDDB_HOST:$CDDB_PORT [$!]"; $return=<$socket>; unless ($return =~ /^2\d\d\s+/) { die "not welcome at cddb db"; } print $socket "cddb hello $HELLO_ID\n"; $return=<$socket>; print STDERR "hello return: $return" if $debug; unless ($return =~ /^2\d\d\s+/) { die "handshake error at cddb db: $CDDB_HOST:$CDDB_PORT"; } print $socket "proto $PROTO_VERSION\n"; $return=<$socket>; print STDERR "proto return: $return" if $debug; unless ($return =~ /^2\d\d\s+/) { die "protokoll mismatch error at cddb db: $CDDB_HOST:$CDDB_PORT"; } print STDERR "cddb: sending: $query\n" if $debug; print $socket "$query\n"; $return=<$socket>; chomp $return; print STDERR "cddb: result: $return\n" if $debug; } elsif ($CDDB_MODE eq "http") { my $query2=$query; $query2 =~ s/ /+/g; my $id=$HELLO_ID; $id =~ s/ /+/g; my $url = "/~cddb/cddb.cgi?cmd=$query2&hello=$id&proto=$PROTO_VERSION"; my $host=$CDDB_HOST; my $port=80; my ($user,$pass); if($HTTP_PROXY) { if($HTTP_PROXY =~ /^(http:\/\/|)(.+?):(.+)\@(.+?):(.+)/) { $user=$2; $pass=$3; $host=$4; $port=$5; } elsif($HTTP_PROXY =~ /^(http:\/\/|)(.+?):(\d+)/) { $host=$2; $port=$3; } $url="http://$CDDB_HOST".$url." HTTP/1.0"; } print STDERR "cddb: connecting to $host:$port\n" if $debug; $socket=IO::Socket::INET->new(PeerAddr=>$host, PeerPort=>$port, Proto=>"tcp",Type=>SOCK_STREAM) or die "cannot connect to cddb db: $host:$port [$!]"; print STDERR "cddb: http send: GET $url\n" if $debug; print $socket "GET $url\n"; if($user) { my $cred = encode_base64("$user:$pass"); print $socket "Proxy-Authorization: Basic $cred\n"; } print $socket "\n"; print $socket "\n" if $FW; if($HTTP_PROXY) { while(<$socket> =~ /^\S+/){}; } $return=<$socket>; chomp $return; print STDERR "cddb: http result: $return\n" if $debug; } else { die "unkown mode: $CDDB_MODE for querying cddb"; } $return =~ s/\r//g; my ($err) = $return =~ /^(\d\d\d)\s+/; unless ($err =~ /^2/) { die "query error at cddb db: $CDDB_HOST:$CDDB_PORT"; } if($err==202) { return undef; } elsif(($err==211) || ($err==210)) { while(<$socket>) { last if(/^\./); push @list,$_; s/\r//g; print STDERR "unexact: $_" if $debug; } } elsif($err==200) { $return =~ s/^200 //; push @list,$return; } else { die "cddb: unknown: $return"; } my @to_get; unless($multi) { if (@list) { my $index; if($input==1) { print "This CD could be:\n\n"; my $i=1; for(@list) { my ($tit) = $_ =~ /^\S+\s+\S+\s+(.*)/; print "$i: $tit\n"; $i++ } print "\n0: none of the above\n\nChoose: "; my $n=; $index=int($n); } else { $index=1; } if ($index == 0) { return undef; } else { push @to_get,$list[$index-1]; } } } else { push @to_get,@list; } my $i=0; for my $get (@to_get) { #200 misc 0a01e802 Meredith Brooks / Bitch Single my ($cat,$id,$at) = $get =~ /^(\S+?)\s+(\S+?)\s+(.*)/; my $artist; my $title; if($at =~ /\//) { ($artist,$title)= $at =~ /^(.*?)\s\/\s(.*)/; } else { $artist=$at; $title=$at; } my %cd=(); $cd{artist}=$artist; chomp $title; $title =~ s/\r//g; $cd{title}=$title; $cd{cat}=$cat; $cd{id}=$id; my @lines; $query="cddb read $cat $id"; if ($CDDB_MODE eq "cddb") { print STDERR "cddb: getting: $query\n" if $debug; print $socket "$query\n"; while(<$socket>) { last if(/^\./); push @lines,$_; } if(@to_get-1 == $i) { print $socket "quit\n"; close $socket; } } elsif ($CDDB_MODE eq "http") { close $socket; my $query2=$query; $query2 =~ s/ /+/g; my $id=$HELLO_ID; $id =~ s/ /+/g; my $url = "/~cddb/cddb.cgi?cmd=$query2&hello=$id&proto=$PROTO_VERSION"; my $host=$CDDB_HOST; my $port=80; my ($user,$pass); if($HTTP_PROXY) { if($HTTP_PROXY =~ /^(http:\/\/|)(.+?):(.+)\@(.+?):(.+)/) { $user=$2; $pass=$3; $host=$4; $port=$5; } elsif($HTTP_PROXY =~ /^(http:\/\/|)(.+?):(\d+)/) { $host=$2; $port=$3; } $url="http://$CDDB_HOST".$url." HTTP/1.0"; } print STDERR "cddb: connecting to $host:$port\n" if $debug; $socket=IO::Socket::INET->new(PeerAddr=>$host, PeerPort=>$port, Proto=>"tcp",Type=>SOCK_STREAM) or die "cannot connect to cddb db: $host:$port [$!]"; print STDERR "cddb: http send: GET $url\n" if $debug; print $socket "GET $url\n"; if($user) { my $cred = encode_base64("$user:$pass"); print $socket "Proxy-Authorization: Basic $cred\n"; } print $socket "\n"; print $socket "\n" if $FW; if($HTTP_PROXY) { while(<$socket> =~ /^\S+/){}; } while(<$socket>) { last if(/^\./); push @lines,$_; } close $socket; } else { die "unkown mode: $CDDB_MODE for querying cddb"; } # xmcd # # Track frame offsets: # 150 # ... # 210627 # # Disc length: 2952 seconds # # Revision: 1 # Submitted via: xmcd 2.0 # for(@lines) { last if(/^\./); next if(/^\d\d\d/); push @{$cd{raw}},$_; #TTITLE0=Bitch (Edit) if(/^TTITLE(\d+)\=\s*(.*)/) { my $t= $2; chop $t; $cd{frames}[$1]=$toc->[$1]->{frames}; $cd{data}[$1]=$toc->[$1]->{data}; unless (defined $cd{track}[$1]) { $cd{track}[$1]=$t; } else { $cd{track}[$1]=$cd{track}[$1].$t; } } elsif(/^DYEAR=\s*(\d+)/) { $cd{'year'} = $1; } elsif(/^DGENRE=\s*(\S+.*)/) { my $t = $1; chop $t; $cd{'genre'} = $t; } elsif(/^\#\s+Revision:\s+(\d+)/) { $cd{'revision'} = $1; } } $cd{tno}=$#{$cd{track}}+1; $cd{frames}[$cd{tno}]=$toc->[$cd{tno}]->{frames}; return %cd unless($multi); push @r,\%cd; $i++; } return @r; } 1; __END__ # Below is the stub of documentation for your module. You better edit it! =head1 NAME CDDB - Read the CDDB entry for an audio CD in your drive =head1 SYNOPSIS use CDDB_get qw( get_cddb ); my %config; # following variables just need to be declared if different from defaults $config{CDDB_HOST}="freedb.freedb.org"; # set cddb host $config{CDDB_PORT}=8880; # set cddb port $config{CDDB_MODE}="cddb"; # set cddb mode: cddb or http $config{CD_DEVICE}="/dev/cdrom"; # set cd device # user interaction welcome? $config{input}=1; # 1: ask user if more than one possibility # 0: no user interaction # get it on my %cd=get_cddb(\%config); unless(defined $cd{title}) { die "no cddb entry found"; } # do somthing with the results print "artist: $cd{artist}\n"; print "title: $cd{title}\n"; print "category: $cd{cat}\n"; print "cddbid: $cd{id}\n"; print "trackno: $cd{tno}\n"; my $n=1; foreach my $i ( @{$cd{track}} ) { print "track $n: $i\n"; $n++; } =head1 DESCRIPTION This module/script gets the CDDB info for an audio cd. You need LINUX, SUNOS or *BSD, a cdrom drive and an active internet connection in order to do that. =head1 INSTALLATION Run "perl Makefile.pl" as usual. ("make", "make install" next) =head1 LICENSE & DISCLAIMER This library is released under the same conditions as Perl, that is, either of the following: a) the GNU General Public License Version 2 as published by the Free Software Foundation, b) the Artistic License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the Artistic License for more details. You should have received a copy of the Artistic License with this Kit, in the file named "Artistic". If not, I'll be glad to provide one. You should also have received a copy of the GNU General Public License along with this program, in the file names "Copying"; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. If you use this library in a commercial enterprise, you are invited, but not required, to pay what you feel is a reasonable fee to the author, who can be contacted at armin@xos.net =head1 AUTHOR & COPYRIGHT (c) 2003 Armin Obersteiner =head1 SEE ALSO perl(1), Linux: F, Solaris, *BSD: F. =cut crip-3.9/criprc_example0000644000000000000000000001721310542056331013743 0ustar rootroot# Charlton's RIP, encode, and tag script rc file: # # Rename this file to .criprc and put in your home directory... # # If any of these are omitted or commented out, the defaults that are # used can be found set at the beginning of the crip script. # Default contact information (please put your e-mail address here) # Example: contact = nobody@nowhere.com contact = # encoders supported are "vorbis" and "flac" encodeto = vorbis # Flags for oggenc (Ogg Vorbis encoder) command. Only used only if # $encodeto is set to "vorbis". # Default is "-q 5" which is generally considered the point at which the # current vorbis codecs attain transparency to source (according to): # http://wiki.hydrogenaudio.org/index.php?title=Ogg_Vorbis # Make sure you are using the best vorbis codec (read this): # http://wiki.hydrogenaudio.org/index.php?title=Recommended_Ogg_Vorbis # Note that "-q 4" is a quality setting roughly equal to 128kbps (average) # and that "-q 3" (roughly 110kbps) is better than even 128kbps VBR MP3. # Hint: If you'd rather put these flags as a command-line option, # use: -o " -q 5" (with a space as the first character within the # quotes so as to not confuse the command-line parser) oggencflags = -q 5 # flacflags: Only used if encodeto is set to "flac". # Note: if you include --ogg as a flag and encode to an ogg-formatted # flac file, crip will try to use metaflac to write the tags and that # seems to fail. I'm not sure what the best way to handle this scenario is. # If anyone out there wants to make flac files within the .ogg framework, # please enlighten me as to 1) why, and 2) what is one supposed to use to # modify comments in this .ogg file, vorbiscomment?! flacflags = --best --replay-gain # Flags for cdparanoia (CD ripper) command. # I like to use "-v -z" here. # If you find the "-v" is too verbose and pointless, feel free to take it # out. That would significantly reduce the size of your terminal output. # I find that using "-z" is good because I like knowing that when the script # finishes cdparanoia did not encounter anything that could lead to an # audible defect. However sometimes the script might hang indefinitely # because of the "-z". If you find that is the case, you can now ctrl-C # during the rip and set new options (say, to "-v --never-skip=40") so that # you can at least go back and listen to see if there were any audible # defects (most of the time there isn't even if the rip wasn't perfect). cdparanoiaflags = -v -z # The first comment field in the tag-info will default be: # "Produced using crip v3.6 (http://bach.dynet.com/crip) on " # (version subject to change accordingly) # If you want a 2nd comment line in your ogg tag, uncomment and edit the # following line: #comment = # Get the title information that goes into the tag either from the # "filename" or the "cddb" info. # Default is "filename", because sometimes the CDDB info is wrong. # Note that if you set this to "cddb" but there isn't any CDDB info, # it'll just set it based on the filename anyway. settitle = filename # editnames: "off" = Use the legacy command-line to edit filenames; # "on" = use an editor; and "both" = use the command-line to edit the # filenames but also asks afterwards if you want to edit the filenames # with the editor. default = "on". editnames = on # Your favorite editor for editing filenames and tag files editor = vim # Normalization is not necessary with replaygain/vorbisgain tags, so # turn off normalization by default. # This option can either be "on" or "off". normalize = off # Volume threshold - if peak vol > 1/$volthresh don't bother normalizing # Default is 1.078. If you set this value real high, your songs probably # won't be normalized but you'll still get the "not normalized, peak=X.XXX" # in your comment (you won't get this in your comment if normalize is off, # but you'll still have peak and group-peak info in your replaygain (vorbisgain) # tags, but these tags are not visible using xmms thru v1.2.7). # If normalize = "off" then $volthresh is ignored. volthresh = 1.078 # trimsilence can either be "on" or "off", depending on whether or not you # want to trim silence off the beginning & end of your track/group. # Note that if you turn both trimsilence and normalize off, you won't need # sox-12.17.0 or wav_find_beginning or wav_find_end. # I personally always set this to "on", but I'm defaulting it to "off" so # that the wav_find_X binaries aren't necessary. It doesn't seem to make # much difference in the final file sizes anyway. trimsilence = off # trimsilargs are the arguments that sox will take to trim the silence # from your tracks (if trimsilence is on in the first place). # A very safe setting is "silence 1 0:0:0.01 -96d" trimsilargs = silence 1 0:0:0.01 -96d # (i.e. anything louder than -96db for more than one hundredth of a second # will be considered the beginning of the sound.) # The type of media that the source comes from (default = "CD") # this just gets put in a comment sourcemedia = CD # Default genre: set to "classical" as default: genre = classical # Default device to rip from cddevice = /dev/cdrom # Turn on/off deletion of wave and tag files. "on" by default for # cleanup purposes. delfiles = on # Classical-style questioning defaults to "off" (because I'm assuming # most people will be ripping 'pop-style' CDs most of the time), askclassical = off # ...unless the genre ends up being "classical", or one of the # classicalgenres specified inside the crip script, which can only # be set inside the script itself. # Skip the album abbreviation question? # (turn this "on" if you never want to be asked for or have the album # abbreviation. If you rip a bunch of classical CDs and don't want # to have to answer null to the album abbreviation question every # time it's asked, but otherwise for non-classical CDs you want to # have the album abbreviation, set to "classical".) # "off", "on", or "classical" - default should be "classical". skipalbumabv = classical # Turn this on to skip the ripping process and create empty .wav files. # By turning this on you will automatically turn on $stopgap so that # you will have a chance to substitute the empty .wav files with the # .wav files that you presumably already have. skiprip = off # Add a 'stop-gap' for allowing user to edit the .wav files before # they are encoded? This is done after the digital silence trimming. stopgap = off # Eject CD when done with it. "off" by default. ejectcd = off # Map euro characters in the default filenames to American characters # (turn "on" if you are an American imperialist) mapeurochars = off # Allow spaces in filenames # I recommend leaving this off because it is bad form to have spaces in # filenames regardless of whether you are on UNIX or Windows. I have included # the option because there are too many Windoze users out there who flooded # the internet with sorry-ass MP3s made with bad encoders, no tag information, # and inappropriate file naming conventions, and who are still too used to # putting spaces in their filenames. I figure having this feature will # encourage them to use this script and make better quality files for # everyone. (no offense to the person who suggested me this feature) # So if you absolutely must have spaces in your filenames, turn # this to "on" (default is "off"). allowspaces = off # This is the e-mail address used to submit new entries to the freedb # CDDB database cddbsubmitaddr = freedb-submit@freedb.org # Directory to write the cddb submit entry file (need to have write # permissions to this directory). cddbsubmitdir = /tmp # The following is the charset for the freedb-submit e-mail: charset = iso-8859-1 crip-3.9/editfilenames0000755000000000000000000000634010702343153013560 0ustar rootroot#!/usr/bin/perl # # Written to suppliment crip with a filename editor. # # Put preferred editor here $editor = "vim"; # Temporary filename $tmpfile = "/tmp/filelist.txt"; # Substitute spaces with an underscore (on/off - default="on") $subsp = "on"; if ($#ARGV >= 0) { # Chop off arguments first $i = 0; while ($ARGV[$i] =~ m/^-(.)/) { $arg[$i] = $1; $i++; } $numargs = $i; # Now chop off any specific filenames passed $j = 0; while ($ARGV[$i] ne "") { $list[$j] = $ARGV[$i]; $chopnl = 0; $i++; $j++; } if ($j == 0) { @list = `ls -1`; $chopnl = 1; } } else { @list = `ls -1`; $chopnl = 1; # will need to chop off newlines from @list } # Now process any arguments if ($numargs > 0) { foreach $arg (@arg) { if ($arg eq "p") { print "Input the prefix to put on each file: "; $prefix = ; chop($prefix); } if (($arg eq "h") || ($arg eq "?") || ($arg eq "-")) { print "Usage: $0 [-p] [-h] [filenames]\n\n"; print " Allows you to quickly and conveniently edit the names of a list of files\n"; print " using your favorite editor. Distributed with crip.\n\n"; print "Options:\n"; print " -p Prompt for a prefix to put onto all the filenames\n"; print " -h, -?, --help Print this help then exit\n"; print "\n"; exit(0); } } } # Create text file to edit open(FILELIST, ">$tmpfile") || die "ERROR: Cannot open tmp file $tmpfile for writing.\n"; $index=0; foreach $file (@list) { $index++; $indexstr = ""; $numzeros = 4 - length($index); foreach $i (1 .. $numzeros) { $indexstr = $indexstr . "0"; } $indexstr = $indexstr . $index; # Now start processing filename if ($chopnl) { chop ($file); } # chop off the \n from the filename # Save this as the old filename $oldfile[$indexstr] = $file; # Now substitute spaces if ($subsp eq "on") { $file =~ s/ /_/g; } # If there's a prefix, add it now... if (defined $prefix) { $file = $prefix . $file; } print FILELIST "$indexstr $file\n"; } close(FILELIST); if ($index == 0) { print "No files.\n"; exit(); } # Edit system "$editor $tmpfile"; $cmdnum = 0; open(FILELIST, "$tmpfile"); while ($line = ) { chop $line; $line =~ s/^(\d\d\d\d) //; $index = $1; $f1 = $oldfile[$index]; $f2 = $line; # Escape character substitutions for $f1 $f1 =~ s/\(/\\(/g; $f1 =~ s/\)/\\)/g; $f1 =~ s/'/\\'/g; $f1 =~ s/`/\\`/g; $f1 =~ s/\"/\\\"/g; $f1 =~ s/ /\\ /g; $f1 =~ s/\;/\\\;/g; $f1 =~ s/,/\\,/g; $f1 =~ s/&/\\&/g; $f1 =~ s/\$/\\\$/g; # Escape character substitutions for $f2 $f2 =~ s/\(/\\(/g; $f2 =~ s/\)/\\)/g; $f2 =~ s/'/\\'/g; $f2 =~ s/`/\\`/g; $f2 =~ s/\"/\\\"/g; $f2 =~ s/ /\\ /g; $f2 =~ s/\;/\\\;/g; $f2 =~ s/,/\\,/g; $f2 =~ s/&/\\&/g; $f2 =~ s/\$/\\\$/g; unless ($f1 eq $f2) { $cmdnum++; $cmd[$cmdnum] = "mv -- $f1 $f2"; print "$cmd[$cmdnum]\n"; } } close(FILELIST); if ($cmdnum == 0) { print "No moves to execute.\n"; exit(); } elsif ($cmdnum == 1) { print "Execute the above move? (y/n): "; } else { print "Execute the above moves? (y/n): "; } $inp = ; chop $inp; if (($inp eq "y") || ($inp eq "Y")) { print "Moving files...\n"; foreach $i (1 .. $cmdnum) { # print "$cmd[$i]\n"; `$cmd[$i]`; } print "Done.\n"; } else { print "Did not do anything.\n"; } crip-3.9/Changelog0000644000000000000000000002206310702357103012633 0ustar rootrootcrip Changelog ============== From v3.8 to 3.9: ----------------- Included patch for using a proxy thru CDDB_get.pm (thanks to Søren Døssing) Fixed version-check for sox >= v13.x.x (thanks to Jack Kelly) Added a work-around for a sox bug that occasionally breaks when using silence and reverse effects at the same time. Added cdparanoia flag suggestions upon interrupt. Added "Moving cdda.wav to..." line right after ripping/cdparanoia command. Included a more recent copy of CDDB_get.pm Bugfix: Fixed various handling of '&', '$' and other special characters. Added version check for metaflac to determine whether to use option --import-vc-from or --import-tags-from. From v3.7 to 3.8: ----------------- Bugfix: -m flag on the command line (Map European to American-only chars) was not being processed (seldom-used) Bugfix: editcomment couldn't handle '&', ',', and ';' in filenames Bugfix: editfilenames couldn't handle filenames starting with '-' (dash) Added --info flag Changed default oggencflags from "-q 4" to "-q 5" (seems like a more reasonable setting these days; also with the latest codecs it is touted that "transparency is achieved" at about this setting...) Changed $skipalbumabv default to "classical" (what I use) and had the info output try to be less confusing. Updated metaflac usage from --import-vc-from to --import-tags-from Updated editcomment to now support .flac files From v3.6 to v3.7: ------------------ Bugfix: editfilenames script now dies if unable to open tmp file. Bugfix: charset freedb submit now specified http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=334535 Bugfix: was failing to remove .rev.wav and .orig.wav files after silence-trimming using the new sox method. Bugfix: Changed tag label "part" to "partnumber" according to convention. Bugfix: Now uses FindBin to locate CDDB_get.pm Other minor changes From v3.5 to v3.6: ------------------ Finally eliminated the dependency on the old version of sox (v.12.17.0) for silence trimming. Fixed comment bug and added comment0 Other minor changes From v3.4 to v3.5: ------------------ Added .criprc config file functionality Attempted to fix bug 276946 from debian bugzilla: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=276946 Unfortunately it is still a problem because some programs the script calls does not seem to have a way to allow dashes in front of it, so I basically don't know how to fix this bug eloquently (without renaming files and such). Suggestions welcomed. Added editfilenames script to package for convenience Other minor changes From v3.3 to v3.4: ------------------ Now supports the FLAC encoder/codec Minor changes to the Usage to support flac Bugfix: When European characters appear in the Album name, the default Album abreviation generator interprets it as a word-boundary Bugfix: If artist (or album) is empty, the CDDB submit DTITLE showed "/ title" (obviously if one of the fields is null you don't need to have " / " anywhere in the title string) Bugfix: If there's no network connection, CDDB lookup will fail and crip dies unexpectedly. Other minor changes From v3.2 to v3.3: ------------------ Added freedb.org CDDB submit feature crip should not need to warn that there could be an audible defect if the track was ripped with the '-z' option, even if it was aborted and reripped. Bugfix: If the title was gotten from the filename, the albumabv and tracknumber would appear in the tag title. From v3.1 to v3.2: ------------------ Bugfix: if crip falls back on the filename to populate the title tag info, it will now use everything after the *first* "_-_" (instead of the last). Bugfix: fixed the fact that it used to be possible for crip to pick null default filenames (""). It now defaults the title to "track_XX" if title is otherwise null. Added warnings for the track groupings and for extensions on filenames. Added $settitle functionality to make it configurable to either get the title string from the filename or the CDDB info. Added the `editcomment` script (to the package - not to the crip script itself) for easily editting the comments of the .ogg file after-the-fact. Added $allowspaces and functionality in order to be able to configure whether or not the script allows spaces in the filenames. Fixed a few typos and misspellings in the script (thanks to Ron Olsen) A number of other minor changes/improvements. From v3.0 to v3.1: ------------------ Added a reminder at the end of the script that if a track is re-ripped without the "-z" flag to "Be sure to listen to it to make sure everything is okay...". Added "-p" flag and functionality which allows a stop-gap (prompt for the user to continue after ripping) to allow the user a chance to edit the raw .wav files before encoding and tagging them. Changed some of the command-line usage and flags to be more straightforward. Also now prints out what the options are set to when starting the script. Added more useful trim information (number of samples and seconds trimmed from the beginning and/or end of the file). It will also now skip the sox command if there's nothing to be trimmed (unless of course it needs to normalize). Added $editnames="both" functionality so that it is possible to edit the filenames on the command-line and also review and edit them afterwards using the editor. From v2.6 to v3.0: ------------------ Added special characters and european characters to be allowed in the computer-chosen default filenames. Added the eurocharacter mapping functionality Changed filnames so that oggenc always encodes a file that ends in ".wav" (this is essentially a bugfix because oggenc will get confused with filenames that have more than one "." in them but do not end in ".wav") Added filename and tag editor functionality. Added $skipalbumabv with functionality Added $ejectcd as an option Added feature to allow 'ctrl-C' during ripping to allow the user to retry cdparanoia with different flags. Other minor functionality, changes, and internal comments (thanks again to Ron Olsen for feature recommendations) From v2.5 to v2.6: ------------------ Submitted by Ron Olsen from Boulder Colorado: Allow cdparanoia options to be specified on command line, Print ripper version and options, Pass device to cdparanoia (fix bug), Allow "`" characters in file names Delete .wav file as soon as it's encoded (otherwise I run out of disk space) Added a comment for ejection of CD at completion of ripping (this can help crank thru multiple crip sessions faster) Made the wave-file deletion an option that's defaulted to "on" Made the classical-style questioning an option, and added logic to allow for which this defaults to (depending on genre). Some other minor comments and changes From v2.4 to v2.5: ------------------ Moved DiscID (CD disc hash used for CDDB queries) from the comment field into an Ogg tag of its own called "discid". The "-??" track suffix was discarded from the comment because the tracknumber is already tagged. Added the "ensemble" question if you have a classical CD but don't put a conductor, or main performer (before it asks you for just the artist). Useful for if you have, say, a string quartet as the artist. Added code that allows command-line flags to be passed to crip (submitted by Daniel Carroll). From v2.0 thru v2.4 (general entry) ----------------------------------- Refined the questions asked to try to be as simple as possible. Refined the Ogg tagging to be as useful and appropriate as possible. I used some of guidelines found at: http://www.reactor-core.org/ogg-tag-standard.html However, I don't find a lot of these tags to be useful (so they have to be user-specified in crip if you want them). From v1.0 to v2.0 ----------------- Converted from encoding in MP3 (using lame) to Ogg Vorbis (since Ogg Vorbis 1.0 was released). I figure it's about time. There are two big reasons to encode in Ogg Vorbis instead of MP3: 1) The quality is definitely better. It is arguable, but the quality of Ogg Vorbis is probably better (per bit) than every other modern codec available out there today (and for the foreseeable future). 2) FAR superior tagging. I don't know about you but I'm really tired of listening to an MP3 and not knowing what I'm listening to or some other essential detail about it and having to look at the CD insert because there wasn't enough room in the tag to put the necessary information. Anyway, those days are over because now we have Ogg Vorbis. I also feel confident in Ogg Vorbis' future. So the choice for me is clear and it should be to everyone else by now. Encode with Ogg Vorbis. So v2.0 addresses this change in my music-file creation mentality. crip v1.0 is actually a very refined MP3 creator and tagger that is the result of years of creating MP3 files of a lot of music (of ALL genres). In refining v1.0 there have probably been a dozen or so versions, but I didn't start keeping version numbers until the creation of v2.0. Charlton Harrison