#!/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 function atExit { echo -en "\033[?25h" # show cursor } trap atExit EXIT # -------------------------------------------------------------- # 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 enhUsage=$"usage: $0 [-t(m|f|o|w)] [-p path] [-e encoder] [-c cddbitem] [-h] [-I interface] [-D device] [-v[v|0]] [-q] [-s] [--help] [--encoding=(m|f|o|w)] [--encoder=(lame|bladeenc)] [--path=] [--interface=(cooked_ioctl|generic_scsi)] [--device=] options: -h | --help: gives this help -v: set verbosity level. -v0 disable all output -v be more verbose -vv enables debug -q: make the script silent. Equivalent to -v0 -t | --encoding: you can specify either m for encoding to mp3 using lame, or f for making lossless encoding using flac, or o for making ogg/vorbis, or w for uncompressed wav. Omitting this results in encoding to flac. mp3s will be placed under a subfolder mp3 and flacs under a subfolder flac -p | --path: specifies the path to save the encoded data. Defaults to the users home directory. -e | --encoder: specifies the mp3 encoder to use. valid encoders are actually: lame,bladeenc Defaults to lame. -c: specifies the CDDB-Entry to use. sometimes there is more than 1 entry for a cd in cddb. Then you can specify wich one to use by this option. You can checkout all entries using cddb.pl. -I | --interface: specifies cdda2wav interface to use. Valid interfaces are generic_scsi and cooked_ioctl. Please note that cooked_ioctl is not available on all systems. Defaults to cooked_ioctl if device begins with /dev else to generic_scsi -D | --device: specifies device to use with cdda2wav. All values that are valid for cdda2wav are valid here. Defaults to /dev/cdrom -s: if set indicates that this disk contains various artists (is a sampler). In this case the artist is written in the title information of cddb most likely. Giving this option the script will show a title list and give the oppotunity to enter a delimiting string so that title and artist information can be split properly and fill the mp3id or whatever correctly. This script uses cdda2wav, cddb and can use various encoders to rip an audio CD." usage=$"usage: $0 [-t(m|f|o|w)] [-p path] [-e encoder] [-c cddbitem] [-h] [-I interface] [-D device] [-v[v|0]] [-q] [-s] options: -h: this help -v: set verbosity level. -v0 disable all output -v be more verbose -vv enables debug -q: make the script silent. Equivalent to -v0 -t: you can specify either m for encoding to mp3 using lame, or f for making lossless encoding using flac, or o for making ogg/vorbis, or w for uncompressed wav. Omitting this results in encoding to flac. mp3s will be placed under a subfolder mp3 and flacs under a subfolder flac -p: specifies the path to save the encoded data. Defaults to the users home directory. -e: specifies the mp3 encoder to use. valid encoders are actually: lame,bladeenc Defaults to lame. -c: specifies the CDDB-Entry to use. sometimes there is more than 1 entry for a cd in cddb. Then you can specify wich one to use by this option. You can checkout all entries using cddb.pl. -I: specifies cdda2wav interface to use. Valid interfaces are generic_scsi and cooked_ioctl. Please note that cooked_ioctl is not available on all systems. Defaults to cooked_ioctl if device begins with /dev else to generic_scsi -D: specifies device to use with cdda2wav. All values that are valid for cdda2wav are valid here. Defaults to /dev/cdrom -s: if set indicates that this disk contains various artists (is a sampler). In this case the artist is written in the title information of cddb most likely. Giving this option the script will show a title list and give the oppotunity to enter a delimiting string so that title and artist information can be split properly and fill the mp3id or whatever correctly. This script uses cdda2wav, cddb and can use various encoders to rip an audio CD." 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: =======" # -------------------------------------------------------------- # -------------------------------------------------------------- # Optionen auswerten (im Moment nur angabe einer alternativen # Konfigurationsdatei, und vebose). Vorher default-werte setzen. # Irgendwie hab ich noch Probleme mit -? das scheint nicht zu funzen. $GETOPT -T >/dev/null 2>&1 if [ $? -eq 4 ] then # enhanced getopt usage="${enhUsage}" TEMP="`$GETOPT -o "?hsv::qt:p:e:c:I:D:" -l "help,encoding:,encoder:,path:,interface:,device:" -- "$@"`" else # old getopt TEMP="`$GETOPT "?hsv::qt:p:e:c:I:D:" "$@"`" fi test $? -ne 0 && { echo -e "${usage}"; exit 1; } # on error eval set -- "$TEMP" # set $1,$2,... taOrder="t" encodingDir=$HOME encodingType="f" encoder="lame" cddbEntry="" cddaIf="" cddaDev="/dev/cdrom" verbose=1 sampler="no" while true do case "$1" in --) shift; break;; -v) # v has an optional argument. As we are in quoted mode, # an empty parameter will be generated if its optional # argument is not found. if [ -z "$2" ] then verbose=2 else case "$2" in v) verbose=3; shift 2;; *) verbose="$2"; shift 2;; esac fi shift 2 ;; -q) verbose=0 shift ;; -t|--encoding) if [ "$2" != "m" -a "$2" != "f" -a \ "$2" != "o" -a "$2" != "w" ] then echo -e "$usage" exit 1 fi encodingType=$2 shift 2 ;; -p|--path) if [ ! \( -d $2 \) ] then echo -e "$usage" exit 1 fi encodingDir=$2 shift 2 ;; -e|--encoder) if [ -z $2 ] then echo -e "$usage" exit 1 fi encoder=$2 shift 2 ;; -c) if [ "$2" -ge 1 ] 2>/dev/null then cddbEntry="$2" cddbEntry=$((cddbEntry-1)) shift 2 else echo -e "$usage" exit 1 fi ;; -I) if [ "$2" != "generic_scsi" -a \ "$2" != "cooked_ioctl" ] then echo -e "$usage" exit 1 fi cddaIf=$2 shift 2 ;; -D) if [ "x" == "x$2" ] then echo -e "$usage" exit 1 fi cddaDev=$2 shift 2 ;; -s) sampler="yes" shift ;; -h|--help|*) echo "${usage}" exit 1 ;; esac done # -------------------------------------------------------------- if [ -z "${cddaIf}" ] then test "${cddaDev%/*}" = "/dev" &&\ cddaIf="cooked_ioctl" ||\ cddaIf="generic_scsi" fi # ---------------------------------------------------------------- # ---------------------------------------------------------------- # 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} # gets all info about the CD. Look in shellUtils for more info. getCDInfo "$sampler" "$cddbEntry" test ${verbose} -ge 1 && echo ${ready} if [ ${verbose} -ge 2 ] then eval "cdInfo=\"$cdInfoMsg\"" cat <<-EOF $cdInfo 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}" < ${dIndex} ${cddbId} ${xml_dText} ${xml_dExtra} ${xml_dArtist} ${xml_dTitle} ${dYear} ${dGenre} ${dLength} ${dTracks} 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}" < $trackNr ${tLength[$i]} ${tStartSec[$i]} ${trackLen} $xml_tArtist $xml_tTitle EOF i=$((i+1)) done echo "" >>"${xmlFile}" test ${verbose} -ge 1 && echo "${ready}" # ---------------------------------------------------------------- # ---------------------------------------------------------------- # now do the ripping test ${verbose} -eq 1 && echo -n "${startRipMsg1}" test ${verbose} -ge 2 && { echo "${startRipMsg2}"; echo -en "\033[?25l"; } 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 outStream="/dev/stdout" else outStream="/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 ) | tr '\r' '\n' |\ sed '/^ [0-9]/!d;/^ *[0-9]*\./d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\ tr -d '\n' >$outStream ;; 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;/^ *[0-9]*\./d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\ tr -d '\n' >$outStream ;; 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;/^ *[0-9]*\./d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\ tr -d '\n' >$outStream ;; 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;/^ *[0-9]*\./d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\ tr -d '\n' >$outStream ;; 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;/^ *[0-9]*\./d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\ tr -d '\n' >$outStream ;; esac test ${verbose} -ge 2 && echo # do a newline after each file i=$((i+1)) done test ${verbose} -ge 2 && echo -en "\033[?25h" test ${verbose} -eq 1 && echo "${ready}" # ----------------------------------------------------------------