You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
497 lines
14 KiB
497 lines
14 KiB
#!/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=<string>] [--interface=(cooked_ioctl|generic_scsi)]
|
|
[--device=<string>]
|
|
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}" <<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}"; 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}"
|
|
# ----------------------------------------------------------------
|