getcd.sh 9.84 KB
#!/bin/bash

# === some global setting & configurations for the script ===
umask 000				# create files with all right for anyone
shopt -s nullglob		# expand patterns which match no file to a null string
shopt -s extdebug

# --------------------------------------------------------------
# das Verzeichnis in dem dieses script liegt herausfinden
scriptDir=${0%/*}
scriptDir="${scriptDir/#\./${PWD}}"
case "${scriptDir}" in /*);; *) scriptDir="${PWD}/${scriptDir}";; esac
# --------------------------------------------------------------

# include helpers
. ${scriptDir}/shellUtils.sh

# --------------------------------------------------------------
# string definitions
usage=$"usage: $0 [-t {m|f|o}] [-p path] [-e encoder] [-c cddb-entry] [-h|-?]
       [-I interface] [-D device] [-v[v]]
\t-t: you can specify either m for encoding to mp3
\t    using lame, or f for making lossless encoding using flac,
\t    or o for making ogg/vorbis, or w for uncompressed wav.
\t    Omitting this results in encoding to flac.
\t    mp3s will be placed under a subfolder mp3 and flacs
\t    under a subfolder flac
\t-p: specifies the path to save the encoded data.
\t    Defaults to the users home directory.
\t-e: specifies the mp3 encoder to use.
\t    valid encoders are actually: lame,bladeenc
\t    Defaults to lame.
\t-c: specifies the CDDB-Entry to use.
\t    sometimes there is more than 1 entry for a cd in cddb.
\t    Then you can specify wich one to use by this option.
\t    You can checkout all entries using cddb.pl.
\t-I: specifies cdda2wav interface to use.
\t    Valid interfaces are generic_scsi and cooked_ioctl.
\t    Please note that cooked_ioctl is not available on all systems.
\t    Defaults to generic_scsi
\t-D: specifies device to use with cdda2wav.
\t    Defaults to /dev/cdrom
\t-v: make the script more verbose. The verbosity level defaults
\t    to 1. When -v is given the level is 2 and -vv increases the 
\t    level to 3, what means give debug output.
\t-q: make the script silent. Equivalent to -v0
\t-h|
\t-?: Shows this help."

ready=$"done"

# level 1 messages
getCDInfoMsg=$"getting cd info..."
outputDirMsg=$"output to: \$encodingDir"
createXmlMsg=$"create xml file..."
startRipMsg1=$"start ripping cd audio data..."

# level 2 messages
encodeMp3Msg=$"Encode to mp3"
encodeFlacMsg=$"Encode to flac"
encodeOggMsg=$"Encode to ogg"
encodeWavMsg=$"Encode to wav"
startRipMsg2=$"start ripping cd audio data:"

cdInfoMsg=$"DISK:
=====
Tracks: \$dTracks
Length: \$dLength
Index:  \$dIndex
Artist: \$dArtist
Title:  \$dTitle
Year:   \$dYear
Genre:  \$dGenre
CDDB:   \$cddbId
Text:   \$dText
Extra:  \$dExtra

TRACKS:
======="
# --------------------------------------------------------------

taOrder="t"
encodingDir=$HOME
encodingType="f"
encoder="lame"
cddbEntry=1
cddaIf="generic_scsi"
cddaDev="/dev/cdrom"
verbose=1

# ----------------------------------------------------------------
# get commandline options
while getopts qvt:p:he:c:I:D: option
do
	case $option in
		t)  
			if [ "${OPTARG}" != "m" -a "${OPTARG}" != "f" -a \
			     "${OPTARG}" != "o" -a "${OPTARG}" != "w" ]
			then
				echo -e "$usage"
				exit 1
			fi
			encodingType=$OPTARG
			;;
		p)
			if [ ! \( -d ${OPTARG} \) ]
			then
				echo -e "$usage"
				exit 1
			fi
			encodingDir=$OPTARG
			;;
		e)
			if [ -z ${OPTARG} ]
			then
				echo -e "$usage"
				exit 1
			fi
			encoder=$OPTARG
			;;
		c)
			if [ ${OPTARG} -lt 1 ]
			then
				echo -e "$usage"
				exit 1
			fi
			cddbEntry=$OPTARG
			;;
		v)
			if [ "${OPTARG}" -a "${OPTARG}" != "0" -a "${OPTARG}" != "v" ]
			then
				echo -e "$usage"
				exit 1
			fi
			test -z "${OPTARG}" && verbose=2
			test "${OPTARG}" = "0" && verbose=0
			test "${OPTARG}" = "v" && verbose=3
			;;
		q)
			verbose=0
			;;
		I)
			if [ "${OPTARG}" != "generic_scsi" -a \
			     "${OPTARG}" != "cooked_ioctl" ]
			then
				echo -e "$usage"
				exit 1
			fi
			cddaIf=$OPTARG
			;;
		D)
			if [ ${OPTARG} -lt 1 ]
			then
				echo -e "$usage"
				exit 1
			fi
			cddaDev=$OPTARG
			;;
		[h\?])
			echo -e "$usage"
			exit 1
			;;
  esac
done
# ----------------------------------------------------------------

echo "verbose: $verbose"

# ----------------------------------------------------------------
# set encodingDir for used encodingType
case ${encodingType} in
	m)
		encodingDir="$encodingDir/mp3"
		test ${verbose} -ge 2 && echo ${encodeMp3Msg}
		;;
	f)
		encodingDir="$encodingDir/flac"
		test ${verbose} -ge 2 && echo ${encodeFlacMsg}
		;;
	o)
		encodingDir="$encodingDir/ogg"
		test ${verbose} -ge 2 && echo ${encodeOggMsg}
		;;
	w)
		encodingDir="$encodingDir/wav"
		test ${verbose} -ge 2 && echo ${encodeWavMsg}
		;;
esac
# ----------------------------------------------------------------

test ${verbose} -ge 1 && echo -n ${getCDInfoMsg}
getCDInfo	# gets all info about the CD. Look in shellUtils for more info.
test ${verbose} -ge 1 && echo ${ready}

if [ ${verbose} -ge 2 ]
then
	cat <<-EOF
		$cdInfoMsg
	EOF

	i=0
	while [ $i -lt ${#tTitle[@]} ]
	do
		echo -n "${tArtist[$i]} - ${tTitle[$i]} "
		echo "([${tStartSec[$i]}-${tEndSec[$i]}] ${tLength[$i]})"
		i=$((i+1))
	done
fi

encodingDir="${encodingDir}/${dArtist}/${dTitle}"
mkdir -p "${encodingDir}"
test ${verbose} -ge 1 && eval "echo ${outputDirMsg}"

# ----------------------------------------------------------------
# fill xml file with data
test ${verbose} -ge 1 && echo -n "${createXmlMsg}"

xmlFile="${encodingDir}/cdinfo.xml"
xml_dText="`echo "${dText}" | recode utf8..h0`"
xml_dExtra="`echo "${dExtra}" | recode utf8..h0`"
xml_dArtist="`echo "${dArtist}" | recode utf8..h0`"
xml_dTitle="`echo "${dTitle}" | recode utf8..h0`"
cat >"${xmlFile}" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cdInfo SYSTEM \"cdInfo.dtd\">
<cdinfo>
	<cdindex>${dIndex}</cdindex>
	<cddb>${cddbId}</cddb>
	<cd-text>${xml_dText}</cd-text>
	<cd-extra>${xml_dExtra}</cd-extra>
	<cd-artist>${xml_dArtist}</cd-artist>
	<cd-title>${xml_dTitle}</cd-title>
	<cd-year>${dYear}</cd-year>
	<cd-genre>${dGenre}</cd-genre>
	<cd-time>${dLength}</cd-time>
	<cd-tracks>${dTracks}</cd-tracks>
	<cd-comment></cd-comment>
EOF

i=0
while [ $i -lt ${#tTitle[@]} ]
do
   trackNr="`printf %02d $((i+1))`"
   xml_tTitle="`echo ${tTitle[$i]} | recode utf8..h0`"
   xml_tArtist="`echo ${tArtist[$i]} | recode utf8..h0`"
	trackEnd=${tEndSec[$i]}
	trackStart=${tStartSec[$i]}
	trackLen=$((trackEnd-$trackStart))

	cat >>"${xmlFile}" <<EOF
	<track>
		<track-number>$trackNr</track-number>
		<track-time>${tLength[$i]}</track-time>
		<track-start-sector>${tStartSec[$i]}</track-start-sector>
		<track-length>${trackLen}</track-length>
		<track-artist>$xml_tArtist</track-artist>
		<track-title>$xml_tTitle</track-title>
		<track-comment></track-comment>
	</track>
EOF
	
	i=$((i+1))
done

echo "</cdinfo>" >>"${xmlFile}"

test ${verbose} -ge 1 && echo "${ready}"
# ----------------------------------------------------------------

# ----------------------------------------------------------------
# now do the ripping
test ${verbose} -eq 1 && echo -n "${startRipMsg1}"
test ${verbose} -ge 2 && echo "${startRipMsg2}"

i=0
while [ $i -lt ${#tTitle[@]} ]
do
	trackNr=$((i+1))

	# now that i don't forget it again. I use tr to translate \r to \n
	# because sed does't recognise a line with only \r at its end as a line.
	# Therefor sed reads until output of cdda2wav ends and does all the
	# processing at once, so the percentage is not shown correctly
	if [ ${verbose} -ge 2 ]
	then
		outCmd="tr '\r' '\n' | 
			sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'\"\${outStr}\"'\1/' |
			tr -d '\n'"
	else
		outCmd="cat >/dev/null"
	fi

	case ${encodingType} in
		f)
   		outFile="`printf %02d ${trackNr}`-${tTitle[$i]}.flac"
      	outStr="track-$trackNr => ${outFile}: "

			( 
				exec 2>&1
				cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - |\
					flac -c -f \
					  -T artist="${tArtist[$i]}" -T album="${dTitle}" \
					  -T genre="${dGenre}" -T title="${tTitle[$i]}" \
					  -T tracknumber="${trackNr}" -T tracknum="${trackNr}" \
					  -T date="${dYear}" -T comment="" \
					  -o "${encodingDir}/${outFile}" - 2>/dev/null
			) | $outCmd
			;;
		m)
   		outFile="`printf %02d ${trackNr}`-${tTitle[$i]}.mp3"
      	outStr="track-$trackNr => ${outFile}: "

			case ${encoder} in
				lame)
					( 
						exec 2>&1
						cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - |\
         				lame -V2 \
			              --ta "${tArtist[$i]}" --tl "${dTitle}" \
			              --tg "${dGenre}" --tt "${tTitle[$i]}" \
			              --tn "${trackNr}" --ty "${dYear}" \
			              --tc "" \
							  - "${encodingDir}/${outFile}" 2>/dev/null
					) | tr '\r' '\n' |\
					sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\
					tr -d '\n'
					;;
				bladeenc)
					( 
						exec 2>&1
						cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - |\
         				bladeenc -progress=0 STDIN \
								"${encodingDir}/${outFile}" 2>/dev/null
					) | tr '\r' '\n' |\
					sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\
					tr -d '\n'
					;;
			esac
			;;
		o)
   		outFile="`printf %02d ${trackNr}`-${tTitle[$i]}.ogg"
      	outStr="track-$trackNr => ${outFile}: "

			( 
				exec 2>&1
				cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - |\
					oggenc -a "${tArtist[$i]}" -l "${dTitle}" \
               	-G "${dGenre}" -t "${tTitle[$i]}" \
               	-N "${trackNr}" -d "${dYear}" \
               	-c "" \
               	-o "${encodingDir}/${outFile}" - 2>/dev/null
			) | tr '\r' '\n' |\
			sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\
			tr -d '\n'
			;;
		w)
   		outFile="`printf %02d ${trackNr}`-${tTitle[$i]}.wav"
      	outStr="track-$trackNr => ${outFile}: "

			( 
				exec 2>&1
				cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - >\
					"${encodingDir}/${outFile}"
			) | tr '\r' '\n' |\
			sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\
			tr -d '\n'
			;;
	esac

	echo	# do a newline after each file
	i=$((i+1))
done

test ${verbose} -eq 1 && echo "${ready}"
# ----------------------------------------------------------------