123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783 |
- #!/bin/sh
- # burncd - Burn audio files to a blank CD.
- # Copyright 2016-2020 orbea
- # All rights reserved.
- #
- # Redistribution and use of this script, with or without modification, is
- # permitted provided that the following conditions are met:
- #
- # 1. Redistributions of this script must retain the above copyright
- # notice, this list of conditions and the following disclaimer.
- #
- # THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
- # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- # This is required for the legacy ash in Slackware and can be removed
- # once ash is no longer included in any supported Slackware releases.
- # shellcheck disable=SC2004
- # https://github.com/koalaman/shellcheck/wiki/SC2004
- tab=' '
- IFS=" $tab
- "
- \unset -f command printf read unalias : 2>/dev/null
- \unalias -a 2>/dev/null
- PATH="$(command -p getconf PATH):$PATH"
- LC_ALL=C; export LC_ALL
- set -euf
- chkdir () {
- if [ ! -d "$1" ]; then
- die 1 "$PRGNAM: '$1': Not a directory." "$help"
- elif [ ! -x "$1" ]; then
- die 1 "$PRGNAM: Cannot open directory '$1': Permission denied." "$help"
- elif [ ! -r "$1" ]; then
- die 1 "$PRGNAM: Cannot read directory '$1': Permission denied." "$help"
- else
- return 0
- fi
- return 1
- }
- chkformat () {
- case "$1" in
- au|flac|mp3|wav ) return 0 ;;
- * ) return 1 ;;
- esac
- }
- chkformat2 () {
- if chkformat "$1"; then
- eval "tmpv=\"\$$2\""
- match "$1" "$tmpv" || eval "$2=\"\$${2} \$1\""
- else
- die 1 "$PRGNAM: Unrecognized audio format '$1'" "$help"
- fi
- }
- chkvar () {
- chkvar=1
- case "$2" in
- ''|CONFIG|PLAYLIST ) addvar "$1" "${2:-files}" ;;
- EXCLUDE|FORMAT ) chkformat2 "$1" "$2" ;;
- INPUT ) ! chkdir "$1" || addvar "${1%${1##*[!/]}}/" "$2" ;;
- * ) eval "$2=\"$1\""; VAR= ;;
- esac
- }
- die () {
- ret="$1"; shift
- case "$ret" in
- : ) printf %s\\n "$@" >&2; return 0 ;;
- 0 ) printf %s\\n "$@" ;;
- * ) printf %s\\n "$@" >&2 ;;
- esac
- exit "$ret"
- }
- escape () {
- word="$1"; base=
- case "$word" in
- *\\*|*\$*|*\"*|*\`* )
- while [ "$word" != '' ]; do
- first="$(printf %s "${word%"${word#?}"}")"
- word="$(printf %s "${word#?}")"
- case "$first" in
- \\|\$|\"|\` ) first="\\$first" ;;
- * ) : ;;
- esac
- base="${base}$first"
- done
- ;;
- * )
- base="$word"
- ;;
- esac
- }
- handleargs () {
- case "$1" in
- -- ) shift; for i do addvar "$i" files; done; return 1 ;;
- - ) while IFS= read -r stdin; do addvar "$stdin" files; done; VAR= ;;
- -c|--config ) VAR=CONFIG ;;
- -C|--cdrecord ) VAR=CDRECORD ;;
- -d|--debug ) DEBUG=1; VAR= ;;
- -e|--exclude ) VAR=EXCLUDE ;;
- -f|--format ) VAR=FORMAT ;;
- -F|--flac ) VAR=FLAC ;;
- -h|--help ) die 0 "$usage" ;;
- -i|--input ) VAR=INPUT ;;
- -M|--mpg123 ) VAR=MPG123 ;;
- -n|--dry-run ) DRYRUN=1; VAR= ;;
- -N|--no-conf ) NOCONFIG=1; VAR= ;;
- -o|--output ) VAR=OUTPUT ;;
- -p|--playlist ) VAR=PLAYLIST ;;
- -S|--sox ) VAR=SOX ;;
- -v|--verbose ) VERBOSE=1; VAR= ;;
- -V|--version ) die 0 "$PRGNAM 0.0" ;;
- -z|--device ) VAR=DEVICE ;;
- --* ) die 1 "$PRGNAM: Unrecognized option '$1'" "$help" ;;
- -* ) shortargs "${1#-}" ;;
- * ) chkvar "$1" "$VAR" ;;
- esac
- }
- shortargs () {
- arg="$1"
- while [ -n "${arg}" ]; do
- flag="$(printf %s "${arg%"${arg#?}"}")"
- arg="$(printf %s "${arg#?}")"
- case "$flag" in
- c ) option=config ;;
- C ) option=cdrecord ;;
- d ) option=debug ;;
- e ) option=exclude ;;
- f ) option=format ;;
- F ) option=flac ;;
- h ) option=help ;;
- i ) option=input ;;
- M ) option=mpg123 ;;
- n ) option=dry-run ;;
- N ) option=no-conf ;;
- o ) option=output ;;
- p ) option=playlist ;;
- S ) option=sox ;;
- v ) option=verbose ;;
- V ) option=version ;;
- z ) option=device ;;
- * ) die 1 "$PRGNAM: Unrecognized option -- '$flag'" "$help" ;;
- esac
- handleargs "--$option"
- [ -z "${VAR}" ] || { [ -z "${arg}" ] || chkvar "$arg" "$VAR"; break; }
- done
- }
- addvar () { escape "$1"; eval "$2=\"\${$2} \\\"\$base\"\\\""; }
- match () { case "$2" in *$1*) return 0 ;; *) return 1 ;; esac; }
- next () { case "$1" in -*) return 0 ;; *) return 1 ;; esac; }
- files=; tmpv=
- CDRECORD=; CONFIG=; DEBUG=; DEVICE=; DRYRUN=; EXCLUDE=; FORMAT=; FLAC=; INPUT=
- MPG123=; NOCONFIG=; OUTPUT=; PLAYLIST=; SOX=; VAR=; VERBOSE=
- PRGNAM=burncd
- CONF=$PRGNAM.conf
- help="Try '$PRGNAM --help' for more information."
- usage="$PRGNAM - Burn audio files to a blank CD from the command line, current
- directory, playlist or standard input.
- Usage: $PRGNAM [OPTIONS] [file ...]
- -c, --config, Path of the configuration files.
- -C, --cdrecord, Path of the cdrecord binary.
- -d, --debug, Debug output from external programs.
- -e, --exclude, Exclude audio formats.
- -f, --format, Choose the audio format.
- -F, --flac, Path of the flac binary.
- -h, --help, Show this help message.
- -i, --input, Path of the default directories.
- -M, --mpg123, Path of the mpg123 binary.
- -n, --dry-run, Enable a test run without burning to a CD.
- -N, --no-conf, Do not load default configuration files.
- -o, --output, Path of the temporary directory.
- -p, --playlist, Read audio files from a playlist.
- -S, --sox, Path of the sox binary.
- -v, --verbose, Verbose logging.
- -V. --version, Show the $PRGNAM version number.
- -z, --device, Path of the CD drive.
- When 'file' is -, read standard input.
- Supported audio formats:
- au, flac, mp3, wav
- Environment variables:
- XDG_CONFIG_HOME : XDG base directory.
- XDG_CONFIG_DIRS : List of colon-separated directories.
- Configuration files:
- $PRGNAM looks for configuration files in the following order:
- 1. \$XDG_CONFIG_HOME/$PRGNAM/$CONF
- (Default: \$HOME/.config/$PRGNAM/$CONF)
- 2. \$HOME/.$CONF
- 3. \$XDG_CONFIG_DIRS/$PRGNAM/$CONF
- (Default: /etc/xdg/$PRGNAM/$CONF)
- 4. /etc/$CONF
- 5. ./$CONF
- To use cdrecord as a normal user:
- # chown root:somegroup /usr/bin/cdrecord
- # chmod 4710 /usr/bin/cdrecord"
- while [ $# -gt 0 ]; do
- chkvar=
- flag="$1"
- handleargs "$@" || break
- shift
- if [ -n "${VAR}" ] && [ -z "${chkvar}" ] && next "${1--}"; then
- next "${flag#-}" ||
- die 1 "$PRGNAM: option requires an argument -- '${flag#-}'" "$help"
- die 1 "$PRGNAM: option '$flag' requires an argument" "$help"
- fi
- done
- chkdep () {
- for deps do
- bin="${deps##*:}"
- DEP="$(exists "$bin")" || return 1
- eval "${deps%:*}=\"\$DEP\""
- done
- return 0
- }
- exists () {
- r=0; cwd="$(pwd)"
- while [ $# -gt 0 ]; do
- v=1; arg="$1"; shift
- case "$arg" in
- ''|*/ )
- :
- ;;
- /* )
- if [ -f "$arg" ] && [ -x "$arg" ]; then
- printf %s\\n "$arg"
- v=0
- fi
- ;;
- ./* )
- if [ -f "$arg" ] && [ -x "$arg" ]; then
- pre="$(cd -- "${arg%%/*}/" && pwd)"
- printf %s\\n "${pre%/}/$arg"
- v=0
- fi
- ;;
- */* )
- if [ -f "$arg" ] && [ -x "$arg" ]; then
- printf %s\\n "$(cd -- "${arg%%/*}/.." && pwd)/$arg"
- v=0
- fi
- ;;
- * )
- if [ -n "${PATH+x}" ]; then
- p=":${PATH:-$cwd}"
- while [ "$p" != "${p#*:}" ] && [ -n "${p#*:}" ]; do
- p="${p#*:}"; x="${p%%:*}"; z="${x:-$cwd}"; d="${z%/}/$arg"
- if [ -f "$d" ] && [ -x "$d" ]; then
- case "$d" in
- /* ) : ;;
- ./* ) pre="$(cd -- "${d%/*}/" && pwd)"; d="${pre%/}/$d" ;;
- * ) d="$(cd -- "${d%/*}/" && pwd)/$arg" ;;
- esac
- printf %s\\n "$d"
- v=0
- break
- fi
- done
- fi
- ;;
- esac
- [ $v = 0 ] || r=1
- done
- return $r
- }
- chkdep FILE:file LS:ls MKDIR:mkdir MV:mv READLINK:readlink RM:rm ||
- die 1 "ERROR: no $bin in ($PATH)"
- skipping="${tab}Skipping"
- # contains: '\r', '^M', ' ', '\t' and '\n'
- SPACE="
$IFS"
- addconf () {
- [ -n "${1}" ] || return 0
- eval "CONF_$var=\"\${2:-$1}\""
- addvar "${tab}$var='$1'" set
- }
- chkconf () {
- case "$1" in
- CDRECORD|DEBUG|DEVICE|DRYRUN|EXCLUDE|FORMAT|FLAC|INPUT|MPG123|OUTPUT|SOX| \
- VERBOSE )
- return 0
- ;;
- esac
- return 1
- }
- chkfile () {
- if [ -h "$1" ]; then
- in="$(command -p "${READLINK:?}" -- "$1")"
- else
- in="$1"
- fi
- shift
- file="$(command -p "${FILE:?}" "$@" "$in")"
- type="$(printf %s "${file#"$in: "}")"
- }
- chktext () {
- if [ ! -r "$1" ]; then
- die : "WARNING: $2 file cannot be read." "$skipping '$1'."
- return 1
- fi
- chkfile "$1" -i --
- case "$type" in
- *empty*|*text* ) return 0 ;;
- * ) die : "WARNING: $2 is not a text file." "$skipping '$1'."; return 1 ;;
- esac
- }
- conf () {
- if chktext "$1" Config; then
- set=
- line=1
- while read -r var chr val cmt; do
- if ! comment "$var"; then
- if [ "$chr" = = ]; then
- if chkconf "$var"; then
- if ! comment "$val"; then
- eval "tmpv=\"\$$var\""
- if empty "$tmpv"; then
- add=
- if [ "$var" = EXCLUDE ] || [ "$var" = FORMAT ]; then
- for i in $(printf %s "$val $cmt"); do
- if comment "$i"; then
- break
- elif chkformat "$i"; then
- match "$i" "$add" || add="${add} $i"
- else
- die : "WARNING: $1:$line:" \
- "$skipping unknown audio format '$i'."
- fi
- done
- addconf "${add# }"
- elif [ "$var" = INPUT ]; then
- for i in $(printf %s "$val $cmt"); do
- if comment "$i"; then
- break
- elif [ ! -d "$i" ]; then
- die : "WARNING: $1:$line:" \
- "${tab}'$i': Not a directory."
- elif [ ! -x "$i" ]; then
- die : "WARNING: $1:$line:" \
- "${tab}Cannot open directory '$i': Permission denied."
- elif [ ! -r "$i" ]; then
- die : "WARNING: $1:$line:" \
- "${tab}Cannot read directory '$i': Permission denied."
- else
- add="${add} \"${i%${i##*[!/]}}/\""
- fi
- done
- addconf "${add# }"
- else
- escape "$val"
- addconf "$base" "$val"
- fi
- match "$var" "$confv" || confv="${confv} $var"
- fi
- [ "$var" = EXCLUDE ] || [ "$var" = FORMAT ] ||
- [ "$var" = INPUT ] || comment "$cmt" ||
- die : "WARNING: $1:$line:" "$skipping excess values '$cmt'."
- fi
- else
- die : "WARNING: $1:$line:" "$skipping unknown variable '$var'."
- fi
- elif comment "$chr"; then
- die : "WARNING: $1:$line:" "${tab}Missing = operand."
- else
- die : "WARNING: $1:$line:" "${tab}Unrecognized character '$chr'."
- fi
- fi
- line=$(($line+1))
- done < "$in"
- addvar "Loaded configuration file '$1'." confl
- [ -z "$set" ] || { eval "set -- $set"
- confl="${confl} $(printf ' "%s"' "$@")"; }
- return 0
- fi
- return 1
- }
- play () {
- if chktext "$1" Playlist; then
- while read -r title; do
- empty "$title" || addvar "$title" files
- done < "$in"
- addvar "Loaded playlist file '$1'." playl
- return 0
- fi
- return 1
- }
- xdgdirs () {
- p=":$1"
- while [ "$p" != "${p#*:}" ]; do
- p="${p#*:}"
- dir="${p%%:*}"
- { ! empty "$dir" && conf "$dir/$PRGNAM/$CONF"; } || continue
- return 0
- done
- return 1
- }
- chkesc () { case "$1" in '') base="$2" ;; *) escape "$2" ;; esac ; }
- comment () { case "$1" in \#*|'') return 0 ;; *) return 1 ;; esac; }
- empty () { case "${1:-}" in *[!$SPACE]*) return 1 ;; *) return 0 ;; esac; }
- exclude () { case "$EXCLUDE" in *$1*) fmt= ;; *) fmt="$2"; suf="$3" ;; esac; }
- printn () { eval "set -- $1"; printf %s\\n $#; }
- quit () { err=$?; eval "set -- $out $tmp"; command -p "${RM:?}" -f -- "$@"; }
- play=; playl=
- eval "set -- $PLAYLIST"
- for f do
- ! play "$f" || play="${play} $f"
- done
- conf=; confl=; confv=
- eval "set -- $CONFIG"
- for f do
- ! conf "$f" || conf="${conf} $f"
- done
- [ -n "${NOCONFIG}" ] || [ -n "${conf}" ] ||
- conf "${XDG_CONFIG_HOME:-${HOME:=}/.config}/$PRGNAM/$CONF" ||
- conf "$HOME/.$CONF" || xdgdirs "${XDG_CONFIG_DIRS:-/etc/xdg}" ||
- conf /etc/$CONF || conf ./$CONF || :
- eval "set -- $confv"
- for var do
- eval "$var=\"\$CONF_$var\""
- done
- if [ -z "${files}" ] && [ -z "${play}" ]; then
- input=
- eval "set -- $INPUT"
- for f do
- empty "$(command -p "${LS:?}" "$f")" || input="${input} \"$f\"*"
- done
- fi
- if [ -n "${files}" ] || [ -n "${play}" ]; then
- eval "set -- $files"
- elif [ -n "${input}" ]; then
- set +f
- eval "set -- $input"
- set -f
- elif [ -z "${INPUT}" ] && ! empty "$(command -p "${LS:?}")"; then
- set +f
- set -- ./*
- set -f
- else
- die 1 'ERROR: Directory is empty.'
- fi
- case "$DRYRUN" in
- 1 ) dry () { :; } ;;
- * ) dry () { "$@"; } ;;
- esac
- case "$VERBOSE" in
- 1 ) log () { printf %s\\n "$@"; } ;;
- * ) log () { :; } ;;
- esac
- case "$DEBUG" in
- 1 ) quiet () { "$@"; } ;;
- * ) quiet () { "$@" 2>/dev/null; } ;;
- esac
- addtrack () {
- track="${2%.*}"
- eval "set -- $1"
- for i do
- a="${i##*/}"
- [ "${a%.*}" != "$track" ] || return 1
- done
- return 0
- }
- DEVICE="${DEVICE:-/dev/sr0}"
- OUTPUT="${OUTPUT:-/tmp/CD}"
- CP='cp'
- CDRECORD="${CDRECORD:-cdrecord}"
- FLAC="${FLAC:-flac}"
- MPG123="${MPG123:-mpg123}"
- SOX="${SOX:-sox}"
- if [ "$VERBOSE" = 1 ]; then
- [ -z "${confl}" ] || ( eval "set -- $confl"; log '' "$@" )
- [ -z "${playl}" ] || ( eval "set -- $playl"; log '' "$@" )
- fi
- log '' 'Configured options:' \
- "${tab}DEVICE = $DEVICE" \
- "${tab}OUTPUT = $OUTPUT" \
- "${tab}Preferred audio formats = ${FORMAT# }" \
- "${tab}Excluded audio formats = ${EXCLUDE# }" \
- "${tab}Playlist files = ${play# }" \
- "${tab}Configuration files = ${conf# }" ''
- if [ -z "${FORMAT}" ]; then
- FORMAT='wav au flac mp3'
- else
- for l in wav au flac mp3; do
- match "$l" "$FORMAT" || FORMAT="${FORMAT} $l"
- done
- fi
- if [ -z "${EXCLUDE}" ]; then
- final="$FORMAT"
- else
- final=
- for l in $(printf %s "$FORMAT"); do
- match "$l" "$EXCLUDE" || final="${final} $l"
- done
- fi
- cmp=; skip=
- au=; flac=; mp3=; wav=
- m=0; n=0
- for f do
- [ -d "$f" ] || [ -r "$f" ] ||
- { die : 'WARNING: File cannot be read.' "$skipping '$f'."; continue; }
- chkfile "$f" --
- case "$type" in
- *FLAC* ) exclude flac farr wav ;;
- *layer\ III* ) exclude mp3 marr wav ;;
- *Sun/NeXT* ) exclude au narr au ;;
- *WAVE* ) exclude wav warr wav ;;
- * ) fmt= ;;
- esac
- if [ -n "${fmt}" ]; then
- if addtrack "$cmp" "${in##*/}"; then
- name="${track%.*}.$suf"
- if [ $m -ge 99 ]; then
- chkesc "$files" "$f"
- skip="$skip \"${tab}$base\""
- continue
- elif [ -e "$OUTPUT/$name" ] || [ -e "$OUTPUT/tmp-$name" ]; then
- die : "WARNING: File found in $OUTPUT." "$skipping '$f'."
- continue
- fi
- m=$(($m+1))
- fi
- chkesc "$files" "$in"
- cmp="$cmp \"$base\""
- cmn="$type::${base}:$n:$fmt:$suf"
- case $fmt in
- farr ) flac="$flac \"${cmn}:\\\$FLAC:16 bit:44.1 kHz:stereo\"" ;;
- marr ) mp3="$mp3 \"${cmn}:\\\$MPG123: :44.1 kHz:Stereo\"" ;;
- narr ) au="$au \"${cmn}:\\\$CP:16-bit:44100 Hz:stereo\"" ;;
- warr ) wav="$wav \"${cmn}:\\\$CP:16 bit:44100 Hz:stereo\"" ;;
- * ) die 1 "ERROR: Unknown format name '$fmt'." ;;
- esac
- n=$(($n+1))
- elif [ -n "${files}" ]; then
- die : 'WARNING: Not a recognized audio file.' "$skipping '$f'."
- fi
- done
- [ -n "${cmp}" ] || die 1 'ERROR: No music files found.'
- if [ -n "${skip}" ]; then
- eval "set -- $skip"
- die : 'WARNING: Audio CDs only allows 99 tracks.' "$skipping:" "$@" ''
- fi
- audio=
- eval "set -- $final"
- for f do
- eval "audio=\"\${audio} \${$f}\""
- done
- cmd=; new=; ord=; out=; req=; tmp=
- farr=; marr=; narr=; warr=
- eval "set -- $audio"
- for f do
- song="${f#*::}"
- for i in cnl khz bit ext end lst pos; do
- eval "$i=\"\${song##*:}\""
- song="${song%:*}"
- done
- addtrack "$new" "${song##*/}" || continue
- var=
- type="${f%%::*}"
- addvar "$song" new
- head="${base##*/}"
- name="${head%.*}.${end:?}"
- ord="$ord \"$OUTPUT/$name:${pos:?}\""
- out="$out \"$OUTPUT/$name\""
- tmp="$tmp \"$OUTPUT/tmp-$name\""
- eval "${lst:?}=\"\${$lst} \\\"\$base\"\\\""
- match "${ext:?}" "$req" || req="${req} $ext"
- for s in "${bit:?}" "${khz:?}" "${cnl:?}"; do
- case "$type" in *$s*) : ;; *)
- case "$s" in
- "$bit" ) var="${var} -b 16" ;;
- "$khz" ) var="${var} -r 44.1k" ;;
- "$cnl" ) var="${var} -c 2" ;;
- esac ;;
- esac
- done
- [ -z "${var}" ] || cmd="$cmd \"$name:${var#"${var%%[! ]*}"}\""
- done
- for prgnam in \$CDRECORD $(printf %s "$req"); do
- dep="$(eval "printf %s \"$prgnam\"")"
- if chkdep "${prgnam#$}:$dep"; then
- log "$(eval "printf %s \"$prgnam\""): ok"
- continue
- elif empty "$dep"; then
- case "$prgnam" in
- \$CDRECORD ) dep=cdrecord ;;
- \$FLAC ) dep=flac ;;
- \$MPG123 ) dep=mpg123 ;;
- * ) die 1 "ERROR: Unknown variable name '$prgnam'." ;;
- esac
- fi
- die 1 "ERROR: no $dep in ($PATH)."
- done
- if SOX="$(exists "$SOX")"; then
- sec=
- eval "set -- $new"
- for t in $(quiet command -p "$SOX" --i -D -- "$@"); do
- sec="$(($sec+$(printf '%.0f' "$t")))"
- done
- dur="$(printf '%dh %dm %ds' $(($sec/3600)) $(($sec%3600/60)) $(($sec%60)))"
- log "$SOX: ok" "Total duration: $dur"
- [ "$sec" -le 4800 ] ||
- die 1 "ERROR: Total duration of $dur exceeds 80 minutes."
- elif [ -n "${cmd}" ]; then
- die 1 'ERROR: sox is required for converting to 16 bit / 44.1 kHz / stereo.'
- else
- die : 'WARNING: sox is required for checking the duration of the audio files.'
- fi
- while [ ! -e "$DEVICE" ]; do
- die : "WARNING: $DEVICE not found." 'Configure the device. (i.e. /dev/sr0)'
- read -r DEVICE
- done
- if [ -z "${DRYRUN}" ]; then
- while :; do
- blank="$(quiet command -p "$CDRECORD" dev="$DEVICE" -minfo)" ||
- die 1 "$CDRECORD: operation failed."
- case "$blank" in *Blank*) : ;; *)
- die : "WARNING: Blank CD not found in $DEVICE." \
- 'Insert a blank CD. Continue? (y/n)'
- read -r answer
- case "$answer" in
- [yY]|[yY][eE][sS] ) continue ;;
- * ) die 0 "Blank CD not found in $DEVICE. Aborting ..." ;;
- esac ;;
- esac
- break
- done
- fi
- log "Using blank CD found in $DEVICE."
- list=; fburn=; fmsg=; mburn=; mmsg=; nburn=; nmsg=; wburn=; wmsg=
- for b in "$farr" "$marr" "$narr" "$warr"; do
- case "$b" in
- '' )
- :
- ;;
- "$farr" )
- fburn="quiet command -p \"\$FLAC\" --output-prefix=\"\$OUTPUT\"/ \
- --decode -- \"\$@\""
- fmsg='Decoding flac files ...'
- list="$list \"'\\\$farr' '\\\$fburn' '\\\$fmsg'\""
- ;;
- "$marr" )
- mburn="for a do fn=\"\${a##*/}\"; quiet command -p \"\$MPG123\" \
- --no-control -w \"\$OUTPUT/\${fn%.*}.wav\" \"\$a\"; done"
- mmsg='Converting mp3 files ...'
- list="$list \"'\\\$marr' '\\\$mburn' '\\\$mmsg'\""
- ;;
- "$narr" )
- nburn="quiet printf '%s\\n' \"\$@\"; for a do fn=\"\${a##*/}\"; \
- command -p \"\$CP\" -- \"\$a\" \"\$OUTPUT/\${fn%.*}.au\"; done"
- nmsg='Copying Sun/NeXT audio files ...'
- list="$list \"'\\\$narr' '\\\$nburn' '\\\$nmsg'\""
- ;;
- "$warr" )
- wburn="quiet printf '%s\\n' \"\$@\"; for a do fn=\"\${a##*/}\"; \
- command -p \"\$CP\" -- \"\$a\" \"\$OUTPUT/\${fn%.*}.wav\"; done"
- wmsg='Copying wav files ...'
- list="$list \"'\\\$warr' '\\\$wburn' '\\\$wmsg'\""
- ;;
- esac
- done
- : "$fburn" "$fmsg" "$mburn" "$mmsg" "$nburn" "$nmsg" "$wburn" "$wmsg" "$CP" \
- "$DEP" "$SPACE"
- command -p "${MKDIR:?}" -p -- "$OUTPUT"
- if [ "$(printn "$list")" -gt 1 ]; then
- out=; n=0
- arg=$(printn "$ord")
- while [ "$(printn "$out")" -lt "$arg" ]; do
- eval "set -- $ord"
- for i do
- if [ "${i##*:}" = $n ]; then
- addvar "${i%:*}" out
- break
- fi
- done
- n=$(($n+1))
- done
- fi
- trap 'quit; trap - EXIT; exit $err' EXIT INT
- eval "set -- $list"
- for i do
- eval "set -- $i"
- eval "burn=$2"
- eval "printf '%s\\n' \"$3\""
- eval "eval \"set -- $1\""
- eval "${burn:?}" || die 1 "ERROR: $PRGNAM operation failed."
- done
- eval "set -- $cmd"
- for i do
- file="${i%:*}"
- opt="${i##*:}"
- log "Converting $file" "sox options: $opt"
- eval "set -- $opt"
- quiet command -p "$SOX" -- "$OUTPUT/$file" "$@" -- "$OUTPUT/tmp-$file"
- command -p "${RM:?}" -f -- "$OUTPUT/$file"
- command -p "${MV:?}" -- "$OUTPUT/tmp-$file" "$OUTPUT/$file"
- done
- eval "set -- $out"
- log 'Burning audio files:' "$@"
- dry quiet command -p "$CDRECORD" dev="$DEVICE" -dao -audio -pad -- "$@"
- die 0 'CD burning finished successfully.'
|