X-Git-Url: https://git.hcoop.net/clinton/abcde.git/blobdiff_plain/12d321a9c8ec1c783a75a77dc71f70d835a720e4..6d81edb6ec135d2c5ef91d77692fb7402e4e86a5:/abcde diff --git a/abcde b/abcde index 8d8151e..7efa584 100755 --- a/abcde +++ b/abcde @@ -22,7 +22,8 @@ echo "Usage: abcde [options] [tracks]" echo "Options:" echo "-1 Encode the whole CD in a single file" echo "-a " -echo " Actions to perform (cddb,read,normalize,encode,tag,move,replaygain,playlist,clean)" +echo " Actions to perform:" +echo " cddb,read,normalize,encode,tag,move,replaygain,playlist,clean" #echo "-A Experimental actions (retag, transcode)" echo "-b Enable batch normalization" #echo "-B Disable batch replaygain (do file by file)" @@ -47,11 +48,12 @@ echo "-N Noninteractive. Never prompt for anything" echo "-m Modify playlist to include CRLF endings, to comply with some players" echo "-M Create a CUE file" echo "-o " -echo " Output file type(s) (vorbis,mp3,flac,spx,mpc,wav). Defaults to vorbis" +echo " Output file type(s) (vorbis,mp3,flac,spx,mpc,wav,m4a). Defaults to vorbis" echo "-p Pad track numbers with 0's (if less than 10 tracks)" echo "-P Use UNIX pipes to read+encode without wav files" echo "-r " echo " Also encode on these remote hosts" +echo "-R Use local CDDB in recursive mode" #echo "-R Add replaygain values to the tag info (only for vorbis,flac,mp3)" echo "-s " echo " Show dielfs from the CDDB info (year,genre)" @@ -106,7 +108,7 @@ f_seq_row () f_seq_line () { i=$1 - if echo i | grep -q "[[:digit:]]" ; then + if echo $i | grep -q "[[:digit:]]" ; then while [ $i -ne `expr $2 + 1` ] do printf $i" " @@ -732,6 +734,9 @@ do_tag () mpc) run_command tagtrack-$OUTPUT-$1 true ;; + m4a) + run_command tagtrack-$OUTPUT-$1 true + ;; wav) run_command tagtrack-$OUTPUT-$1 true ;; @@ -814,6 +819,9 @@ do_encode () mpc) TEMPARG="PIPE_$MPPENCODER" ;; + m4a) + TEMPARG="PIPE_$MPPENCODER" + ;; esac IN="$( eval echo "\$$TEMPARG" )" else @@ -932,6 +940,15 @@ do_encode () ## FIXME ## to the encoder ends up empty. $RUN_COMMAND nice $ENCNICE $MPPENCODER $MPPENCODEROPTS --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" --year "$CDYEAR" --comment "$COMMENT" "$IN" "$OUT" ;; + m4a) + # Quick hack to avoid tagging Ogg/Speex, since there is no other way to tag than inline tagging + if [ ! "$DOTAG" = "y" ]; then + $RUN_COMMAND nice $ENCNICE $AACENCODER $AACENCODEROPTS --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" --year "$CDYEAR" --comment "$COMMENT" -o "$OUT" "$IN" + + else + $RUN_COMMAND nice $ENCNICE $AACENCODER $AACENCODEROPTS -o "$OUT" "$IN" + fi + ;; wav) # In case of wav output we need nothing. Just keep the wavs. ;; @@ -1334,7 +1351,11 @@ do_discid () if [ "$CDROMREADERSYNTAX" = "flac" ] ; then TRACKINFO=$($METAFLAC $METAFLACOPTS --export-cuesheet-to=- $CDROM | $CUE2DISCID) else - TRACKINFO=$($CDDISCID $CDROM) + case "$CDDBMETHOD" in + cddb) TRACKINFO=$($CDDISCID $CDROM) ;; + # FIXME # musicbrainz needs a cleanup + musicbrainz) TRACKINFO=$($MUSICBRAINZ -c $CDROM ) ;; + esac fi # Make sure there's a CD in there by checking cd-discid's return code if [ ! "$?" = "0" ]; then @@ -1384,6 +1405,11 @@ do_discid () TRACKS="$(echo "$CDPARANOIAOUTPUT" | egrep '^[[:space:]]+[[:digit:]]' | tail -n 1 | get_first | tr -d "." | tr '\n' ' ')" CDPARANOIAAUDIOTRACKS="$TRACKS" else + # Previous versions of abcde would store the tracks on a file, instead of the status record. + if [ -f "$ABCDETEMPDIR/cdparanoia-audio-tracks" ]; then + echo cdparanoia-audio-tracks=$( cat "$ABCDETEMPDIR/cdparanoia-audio-tracks" ) >> "$ABCDETEMPDIR/status" + rm -f "$ABCDETEMPDIR/cdparanoia-audio-tracks" + fi if [ -f "$ABCDETEMPDIR/status" ] && TRACKS=$(checkstatus cdparanoia-audio-tracks); then :; else TRACKS=$(echo $TRACKINFO | cut -f2 -d' ') fi @@ -1470,7 +1496,7 @@ do_discid () exit 1 fi rm -rf "$ABCDETEMPDIR" || exit 1 - mkdir "$ABCDETEMPDIR" + mkdir -p "$ABCDETEMPDIR" if [ "$?" -gt "0" ]; then # Directory already exists or could not be created echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2 @@ -1492,13 +1518,15 @@ do_discid () fi else # We are starting from scratch - mkdir "$ABCDETEMPDIR" + mkdir -p "$ABCDETEMPDIR" if [ "$?" -gt "0" ]; then # Directory already exists or could not be created echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2 exit 1 fi cat /dev/null > "$ABCDETEMPDIR/status" + # Store the abcde version in the status file. + echo "abcde-version=$VERSION" >> "$ABCDETEMPDIR/status" fi if [ X"$MAKECUEFILE" = "Xy" -a X"$WEHAVEACD" = "Xy" ]; then if checkstatus cuefile > /dev/null 2>&1 ; then :; else @@ -1522,6 +1550,9 @@ do_discid () # Create the discid file echo "$TRACKINFO" > "$ABCDETEMPDIR/discid" + if checkstatus cddbmethod > /dev/null 2>&1 ; then :; else + echo "cddbmethod=$CDDBMETHOD" >> "$ABCDETEMPDIR/status" + fi } # do_cleancue @@ -1593,43 +1624,72 @@ do_localcddb () CDDBLOCALSUCCESS="n" CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1) - CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}" USELOCALRESP="y" - - # If the user has selected to check a local CDDB repo, we proceed with it - if [ -r "${CDDBLOCALFILE}" ]; then - # List out disc title/author and contents - do_cddbparse "${CDDBLOCALFILE}" - echo -n "Locally cached CDDB entry found, use it? [y/n] (y): " - if [ "$INTERACTIVE" = "y" ]; then - read USELOCALRESP - while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do - echo -n 'Invalid selection. Please answer "y" or "n": ' - read USELOCALRESP - done - [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y" - else - echo "y" >&2 - fi - if [ "$USELOCALRESP" = "y" ]; then - #echo "Using local copy of CDDB data" - echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "$ABCDETEMPDIR/cddbread.1" - cat "${CDDBLOCALFILE}" >> "$ABCDETEMPDIR/cddbread.1" - echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB - echo cddb-readcomplete >> "$ABCDETEMPDIR/status" - do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices" - echo cddb-choice=1 >> "$ABCDETEMPDIR/status" - CDDBLOCALSUCCESS="y" + + if [ "$CDDBLOCALRECURSIVE" = "y" ]; then + CDDBLOCALRESULTS="$(find ${CDDBLOCALDIR} -name "${CDDBDISCID}" -type f 2> /dev/null)" + if [ "$(echo "${CDDBLOCALRESULTS}" | wc -l)" = "1" ]; then + CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBLOCALRESULTS}" + CDDBLOCALMATCH=single + elif (( $(echo "${CDDBLOCALRESULTS}" | wc -l) > 1 )); then + CDDBLOCALMATCH=multiple else - #echo "Not using local copy of CDDB data" - CDDBLOCALSUCCESS="n" + CDDBLOCALMATCH=none fi + elif [ -r "${CDDBLOCALDIR}/${CDDBDISCID}" ]; then + CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}" + CDDBLOCALMATCH=single else - CDDBLOCALSUCCESS="n" + CDDBLOCALMATCH=none fi + + # If the user has selected to check a local CDDB repo, we proceed with it + case $CDDBLOCALMATCH in + single) + # List out disc title/author and contents + do_cddbparse "${CDDBLOCALFILE}" + echo -n "Locally cached CDDB entry found, use it? [y/n] (y): " + if [ "$INTERACTIVE" = "y" ]; then + read USELOCALRESP + while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do + echo -n 'Invalid selection. Please answer "y" or "n": ' + read USELOCALRESP + done + [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y" + else + echo "y" >&2 + fi + if [ "$USELOCALRESP" = "y" ]; then + #echo "Using local copy of CDDB data" + echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "$ABCDETEMPDIR/cddbread.1" + cat "${CDDBLOCALFILE}" >> "$ABCDETEMPDIR/cddbread.1" + echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB + echo cddb-readcomplete >> "$ABCDETEMPDIR/status" + do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices" + echo cddb-choice=1 >> "$ABCDETEMPDIR/status" + CDDBLOCALSUCCESS="y" + else + #echo "Not using local copy of CDDB data" + CDDBLOCALSUCCESS="n" + fi + ;; + none) + CDDBLOCALSUCCESS="n" + ;; + esac fi } +do_musicbrainzstat () +{ + : +} + +do_musizbrainz () +{ + : +} + # do_cddbstat do_cddbstat () { @@ -1822,6 +1882,13 @@ do_cddbedit () CHOICE=$(checkstatus cddb-choice) if [ -n "$CHOICE" ] ; then case $CDDBCHOICES in + -1) if head -1 "$ABCDETEMPDIR/cddbquery" | grep -q "^$" ; then + log error "CDDB query failed!" + exit 1 + else + cat "$ABCDETEMPDIR/cddbchoices" + fi + ;; 1) cat "$ABCDETEMPDIR/cddbchoices" ;; *) echo "Selected: #$CHOICE" @@ -1845,16 +1912,15 @@ do_cddbedit () echo -n "Which entry would you like abcde to use (0 for none)? [0-$CDDBCHOICES]: " >&2 read CDDBCHOICE [ X"$CDDBCHOICE" = "X" ] && CDDBCHOICE=1 - if echo $CDDBCHOICE | egrep -q "[[:digit:]]+,[[:digit:]]+" ; then + if echo $CDDBCHOICE | egrep -q "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" ; then if [ ! X"$DIFF" = "X" ]; then - PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1) - PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2) + PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null) + PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null) if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBCHOICES ] || \ [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBCHOICES ] || \ [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then echo "Invalid diff range. Please select two coma-separated numbers between 1 and $CDDBCHOICES" >&2 else - # We parse the 2 choices to diff, store them in temporary files and diff them. for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do do_cddbparse "$ABCDETEMPDIR/cddbread.$PARSECHOICE" > "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE" @@ -1870,10 +1936,10 @@ do_cddbedit () else echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBCHOICES." >&2 fi - else + elif echo $CDDBCHOICE | egrep -q "[[:space:]]*[[:digit:]]+[[:space:]]*" ; then + # Make sure we get a valid choice + CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null) if [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; then - # Make sure we get a valid choice - CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null) echo "Invalid selection. Please choose a number between 0 and $CDDBCHOICES." >&2 fi fi @@ -2136,6 +2202,13 @@ do_cdread () FIRSTTRACK=$2 LASTTRACK=$3 UTRACKNUM=$FIRSTTRACK + case "$CDROMREADERSYNTAX" in + flac) READTRACKNUMS="$FIRSTTRACK.1-$(($LASTTRACK + 1)).0" ;; + cdparanoia) READTRACKNUMS="$FIRSTTRACK-$LASTTRACK" ;; + cdda2wav) READTRACKNUMS="$FIRSTTRACK+$LASTRACK" ;; + *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode" + exit 1 ;; + esac else UTRACKNUM=$1 fi @@ -2177,6 +2250,7 @@ do_cdread () flac) nice $READNICE $FLAC -d --cue=${READTRACKNUMS:-$UTRACKNUM.1-$(($UTRACKNUM + 1)).0} "$FILEARG" "$CDROM" ;; cdparanoia) + echo "nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;;" > /tmp/log nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;; cdda2wav) if [ "$OSFLAVOUR" = "OSX" ] ; then @@ -2314,6 +2388,10 @@ post_read () ############################################################################### # Builtin defaults + +# CDDB +# Defaults to FreeDB, but a python musicbrainz can be used +CDDBMETHOD=cddb CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi" CDDBSUBMIT=freedb-submit@freedb.org CDDBPROTO=5 @@ -2326,7 +2404,7 @@ CDDBUSELOCAL="n" SHOWCDDBFIELDS="year,genre" INTERACTIVE=y -CDROMREADERSYNTAX=cdparanoia +#CDROMREADERSYNTAX=cdparanoia ENCODERSYNTAX=default MP3ENCODERSYNTAX=default @@ -2334,6 +2412,7 @@ OGGENCODERSYNTAX=default FLACENCODERSYNTAX=default SPEEXENCODERSYNTAX=default MPPENCODERSYNTAX=default +AACENCODERSYNTAX=default NORMALIZERSYNTAX=default CUEREADERSYNTAX=default @@ -2385,6 +2464,8 @@ FLAC=flac SPEEXENC=speexenc # mpp (Musepack) MPPENC=mppenc +# m4a +AACENC=faac ID3=id3 ID3V2=id3v2 @@ -2395,6 +2476,7 @@ DAGRAB=dagrab CDDAFS=cp CDDISCID=cd-discid CDDBTOOL=cddb-tool +MUSICBRAINZ=musicbrainz-get-tracks EJECT=eject MD5SUM=md5sum DISTMP3=distmp3 @@ -2428,6 +2510,8 @@ FLACOPTS= SPEEXENCOPTS= # mpc MPPENCOPTS= +# m4a +AACENCOPTS= ID3OPTS= ID3V2OPTS= @@ -2453,10 +2537,13 @@ MAXPROCS=1 # List of actions to perform - by default, run to completion ACTIONS=cddb,read,encode,tag,move,clean +# This option is basicaly for Debian package dependencies: # List of prefered outputs - by default, run with whatever we have in the path -# This option is basicaly for Debian package dependencies DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:lame,mp3:bladeenc,spx:speex +# List of prefered cdromreaders - by default, run whichever we have in the path +DEFAULT_CDROMREADERS="cdparanoia cdda2wav" + # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for Linux/OpenBSD/NetBSD. # Let's use these checkings to determine the OS flavour, which will be used later if [ X$(uname) = "XFreeBSD" ] ; then @@ -2607,6 +2694,21 @@ fi # If the user provided a DISCID, disable eject if [ -n "$DISCID" ]; then EJECTCD=n ; fi +# Check the available cd rippers in the system, from the ones we know. +if [ "$CDROMREADERSYNTAX" = "" ]; then + for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do + if [ -x $( which $DEFAULT_CDROMREADER ) ]; then + CDROMREADERSYNTAX=$DEFAULT_CDROMREADER + break + fi + done + if [ "$CDROMREADERSYNTAX" = "" ]; then + log error "no cdreader found in your PATH" + log error "hints: are all dependencies installed? has the \$PATH been modified?" + exit 1 + fi +fi + # Decide if we can continue. if [ "$ONETRACK" = "y" ]; then # FIXME # remove check as soon as we find out about the other readers @@ -2829,6 +2931,7 @@ if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;; spx:*) SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;; mpc:*) MPPENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;; + m4a:*) AACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;; esac done for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do @@ -2838,7 +2941,8 @@ if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then OUTPUTTYPE="$TEMPOUTPUTTYPE" fi -# If nothing has been specified, use oggenc for oggs and lame for mp3s and flac for flacs and speexenc for speex and mppenc for mpps +# If nothing has been specified, use oggenc for oggs and lame for mp3s and flac +# for flacs and speexenc for speex and mppenc for mpps and faac for m4as # Getting ready for multiple output changes for OUTPUT in $(echo $OUTPUTTYPE | tr , \ ) @@ -2868,6 +2972,9 @@ do [ "$MPPENCODERSYNTAX" = "default" ] && MPPENCODERSYNTAX=mppenc [ "$DOREPLAYGAIN" = "y" ] && NEEDMPPGAIN=y ;; + m4a) + [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac + ;; wav) if [ "$KEEPWAVS" = "y" ]; then vecho "Unsetting the KEEPWAVS option, since the resulting wav files were requested..." @@ -2948,7 +3055,12 @@ case "$MPPENCODERSYNTAX" in MPPENCODER="$MPPENC" ;; esac - +case "$AACENCODERSYNTAX" in + faac) + AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}" + AACENCODER="$AACENC" + ;; +esac # and which tagger if [ "$ID3TAGV" = "1" ]; then @@ -2973,6 +3085,12 @@ case "$CUEREADERSYNTAX" in ;; esac +# which information retrieval tool are we using? +case "$CDDBTOOL" in + cddb) ;; + musicbrainz) ;; +esac + # Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then log error "FLAC on an Ogg container is not yet supported" @@ -3006,7 +3124,11 @@ if [ "$EJECTCD" = "y" ]; then NEEDEJECT=y fi if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then - NEEDHTTPGET=y + if [ "$CDDBMETHOD" = "cddb" ]; then + NEEDHTTPGET=y + elif [ "$CDDBMETHOD" = "musicbrainz" ]; then + : + fi fi if [ "$MAKECUEFILE" = "y" ]; then NEEDCUEREADER=y @@ -3110,16 +3232,25 @@ fi export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM -# User-definable function to set some things. Use it for -# - closing the CD tray with eject -t -# - set the CD speed value with eject -x -vecho -n "Executing customizable pre-read function... " +if [ "$DOREAD" = "y" ]; then + # User-definable function to set some things. Use it for + # - closing the CD tray with eject -t + # - set the CD speed value with eject -x + vecho -n "Executing customizable pre-read function... " -pre_read # Execute the user-defined pre-read funtion. Close the CD with it. + pre_read # Execute the user-defined pre-read funtion. Close the CD with it. -vecho "done." + vecho "done." +fi -do_discid # Get ABCDETEMPDIR created and status file initialized +case "$CDDBMETHOD" in + cddb) + do_discid # Get ABCDETEMPDIR created and status file initialized + ;; + musicbrainz) + do_musicbrainz + ;; +esac if [ "$DOCDDB" = "y" ]; then if [ $CDDBUSELOCAL = "y" ]; then @@ -3129,9 +3260,16 @@ if [ "$DOCDDB" = "y" ]; then : else if [ ! "$CDDBLOCALSUCCESS" = "y" ] ; then - do_cddbstat - do_cddbquery - do_cddbread + case "$CDDBMETHOD" in + cddb) + do_cddbstat + do_cddbquery + do_cddbread + ;; + musicbrainz) + do_musicbrainz + ;; + esac fi fi do_cddbedit