Permalink
Fetching contributors…
Cannot retrieve contributors at this time
executable file 1141 lines (1016 sloc) 25.5 KB
#!/bin/bash
#
# This file is part of fadecut
# https://github.com/fadecut/fadecut
#
# fadecut is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# fadecut is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with fadecut. If not, see <http://www.gnu.org/licenses/>.
# Script exit codes ------------------------------------------------------------
# Returnvalues : 0 - successfully
# 1 - partionally unsuccuessfully
# 2 - function unexpected aborted
# 3 - action aborted
# 4 - syntax error
# 5 - couldn't read, write or find file
# 6 - invalid status
# 99 - undefinded error code
#
# Constants --------------------------------------------------------------------
#
# you may overwrite all this constants in
# ~/.fadecut/fadecutrc
# and/or
# ~/.fadecut/profiles/<profile>
#
FILES=*.mp3 # which files to work on
ENCODING=ogg # target format [opus/ogg/mp3]
TRIM_BEGIN=0 # trim n seconds at beginning
TRIM_END=0 # trim n seconds at end of song
FADE_IN=1 # seconds to fade in
FADE_OUT=4 # seconds to fade out
PWD=$(pwd) # main directory of fadecut
LOGDIR=/tmp # where to write logfiles
PROFILEDIR="$HOME/.fadecut" # profiledir
WORKDIR="$PWD" # workdir
OUTPUTDIR="$PWD/new" # where to put fadecut'ted files
ORIGDIR="$PWD/orig" # where to put original files
DONEDIR="$PWD/done" # here the user puts finished
# files, which are tested and
# listened
DONTLIKEDIR="$PWD/dontlike" # here are songs we don't like
ERRORDIR="$PWD/error" # files had an error
TMPDIR=/tmp # here to put temporary files
ENQUEUE=0 # enqueue to rhythmbox or vlc
KEEPORIG=0 # don't keep original files
DEBUG=0 # debug level 0-3
VERBOSE=1 # verbosity level
LOOP_INTERVAL=10 # loop interval in seconds
RESTART_STREAMRIPPER_INTERVAL=900 # restart interval streamripper
STREAMRIPPER_START=0 # start streamripper [0/1]
USER_AGENT="Streamripper/1.x" # streamripper useragent
STREAMRIPPER_OPTS="-o always -T" # streamripper options
E_NOARGS=65 # standard errorlevel definition
PID=$$ # fadecut's pid
# define all binaries
BIN_STREAMRIPPER=$(which streamripper)
BIN_SOX=$(which sox)
BIN_OPUSINFO=$(which opusinfo)
BIN_OPUSENC=$(which opusenc)
BIN_OGGINFO=$(which ogginfo)
BIN_OGGENC=$(which oggenc)
BIN_ID3V2=$(which id3v2)
BIN_LAME=$(which lame)
BIN_MEDIAINFO=$(which mediainfo)
# Variables --------------------------------------------------------------------
PidStreamripper="-1"
IdleCounter=-1
IdleSeconds=0
MissingVar=""
Fdst=""
PostExit=0 # Used for delayed shutdown's
Editor=vi
if [ -n "$EDITOR" ]; then
Editor="$EDITOR"
fi
# Functions --------------------------------------------------------------------
usage()
#
# Description: shows help text
#
# Parameter : none
#
# Output : shows help text
#
{
cat << EOF
usage: $(basename $0) -p <profilename> [other options]
OPTIONS:
-c create profile <profilename>
-d Debug: -d 0|1|2|3 (level 0 is standard, -d without number is like 1)
-e edit profile <profilename>
-h Show this message
-i optional input directory
-k keep original file
-l list all existing profiles
-o optional output directory
-p Profile <profilename>
-q Quiet
-r Stream (and rip), start streamripper
-v Verbose
examples:
if you want to rip audio from a radio station:
$(basename $0) -p swisspop -r
if you just want to process some files out of a directory:
$(basename $0) -p swisspop -i <input-directory>
(Warning: files will be deleted from <input-directory>!
use option -k to keep them in ./orig)
EOF
return 0
}
logging()
#
# Description: It writes messages to logfile or standard output.
#
# Parameter : $1 - the level of message
# $2 - the message
#
# Std. Output: Logging messages.
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
logtime="$(date +%H):$(date +%M):$(date +%S)"
prefix=""
stderr=-1
case $1 in
-e) prefix="Error: " stderr=1 verbose=0;; #show always
-s) prefix="Success: " stderr=0 verbose=0;; #show always
-r) prefix="Stream: " stderr=0 verbose=0;; #show always
-i) prefix="Info: " stderr=0 verbose=1;; #show in VERBOSE>=1 mode
-a) prefix=" " stderr=0 verbose=1;; #show in VERBOSE>=1 mode
-n) prefix="Notice: " stderr=0 verbose=2;; #show in VERBOSE>1 mode
-w) prefix="Warning: " stderr=1 verbose=2;; #show in VERBOSE>1 mode
-d) prefix="Debug: " stderr=1 verbose=3;; #show only in DEBUG mode
esac
shift
# if VERBOSE mode is set, then show all messages, which we want to show in verbose mode
if [ $VERBOSE -ge 1 ] && [ $verbose -lt 2 ] ; then
if [ "$stderr" -eq 1 ]; then
echo "$logtime $prefix" $1 >&2
else
echo "$logtime $prefix" $1
fi
elif [ $VERBOSE -gt 1 ] && [ $verbose -lt 3 ] ; then
if [ "$stderr" -eq 1 ]; then
echo "$logtime $prefix" $1 >&2
else
echo "$logtime $prefix" $1
fi
# else show only messages which are defined to show in non-verbose mode
elif [ $verbose -eq 0 ] ; then
if [ "$stderr" -eq 1 ]; then
echo "$logtime $prefix" $1 >&2
else
echo "$logtime $prefix" $1
fi
fi
# show debug messages
if [ $DEBUG -ge 1 ] && [ $verbose -eq 3 ] ; then
echo "$logtime $prefix" $1 >&2
fi
}
createDirs()
#
# Description: creates needed directories
#
# Parameter : none
#
# Output : none
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
if [ ! -d "$PROFILEDIR/profiles" ]; then
mkdir -p "$PROFILEDIR/profiles"
fi
return 0
}
startStream()
#
# Description: forks the streamripper process
#
# Parameter : none
#
# Output : none
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
cd "$WORKDIR"
if [ ! -x $BIN_STREAMRIPPER ]; then
logging -e "Ooops! Streamripper not found"
shutdown_fadecut 3
fi
if [ ! -d "/proc/$PidStreamripper" ] && [ "$STREAMRIPPER_START" == "1" ];
then
$BIN_STREAMRIPPER $STREAM_URL -d . \
--codeset-filesys=utf8 \
--codeset-id3=ISO-8859-1 \
-u $USER_AGENT \
-s $STREAMRIPPER_OPTS \
> $LOGDIR/fadecutstream-$PID.log 2>&1 &
PidStreamripper=$!
logging -s "$BIN_STREAMRIPPER started pid=$PidStreamripper"
else
logging -n "$BIN_STREAMRIPPER running pid=$PidStreamripper"
fi
cd "$PWD"
return 0
}
shutdown_streamripper()
#
# Description: shutting down streamripper
#
# Parameter : none
#
# Output : logging
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
TmpPid=$(pidof streamripper)
if [ -z "$TmpPid" ]; then return 0
fi
if [[ " $TmpPid " == *" $PidStreamripper "* ]];
then
logging -i "Shuting down streamripper"
kill $PidStreamripper
sleep 1
if [[ " $(pidof streamripper) " == *" $PidStreamripper "* ]];
then
logging -w "Streamripper still here, killing it!"
kill -9 $PidStreamripper
fi
else
logging -n "Another streamripper is still running"
fi
return 0
}
shutdown_fadecut()
#
# Description: shutting down fadecut and cleaning up
#
# Parameter : none
#
# Output : logging
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
logging -n "Shutting down fadecut..."
ExitCode=$1
shutdown_streamripper
if [ -f "$LOGDIR/fadecutstream-$PID.log" ] ; then
rm $LOGDIR/fadecutstream-$PID.log
fi
case $ExitCode in
0)
logging -s "Fadecut exiting..."
;;
1)
logging -w "Fadecut stopped partionally unsuccuessfull"
;;
esac
logging -d "Returnvalue=$ExitCode"
exit $ExitCode
}
queueSong()
#
# Description: queue song to music player
#
# Parameter : none
#
# Output : logging
#
{
if [ $DEBUG -ge 2 ]; then set -x
fi
if [ $ENQUEUE -eq "1" ]; then
if [ "$(pidof rhythmbox)" ];
then
logging -i "Rhythmbox is running, adding to playlist"
rhythmbox-client --enqueue "$OUTPUTDIR"/"$Fdst"
fi
if [ "$(pidof vlc)" ];
then
# enqueue to vlc player if in one instance mode (default disabled)
logging -i "vlc is running, adding to playlist"
vlc --playlist-enqueue "$OUTPUTDIR"/"$Fdst" > /dev/null 2>&1
fi
fi
return 0
}
control_c()
#
# Description: run if user hits control-c
#
# Parameter : none
#
# Output : logging
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
logging -n "CTRL-C catched"
shutdown_fadecut 0
}
loop_fadecut()
#
# Description: main processing function of fadecut
#
# Parameter : none
#
# Output : none
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
RetLoop=0
cd "$WORKDIR"
for F in $FILES
do
# if there are no more files to process, go to idle state or clean up
# and shutdown fadecut.
if [ "$F" == "$FILES" ]; then
let IdleCounter=$((IdleCounter+1))
let IdleSeconds=$((IdleCounter*LOOP_INTERVAL))
logging -n "no files to process, idle for $IdleSeconds seconds"
if [ $STREAMRIPPER_START == "0" ];
then
shutdown_fadecut $PostExit
else
if [ $IdleSeconds -ge $RESTART_STREAMRIPPER_INTERVAL ];
then
logging -w "Oops! Seems to hang, restarting it"
shutdown_streamripper
startStream
IdleCounter=0
fi
fi
break
fi
IdleCounter=0
# Checking part of loop_fadecut()
# check next file
logging -i "Processing: $F"
Fstatus="processing"
Fnew=$(filerename $F)
# Converting id3v1->id3v2 tags, if necessary. Must be before `id3v2 -l`
# command.
$BIN_ID3V2 -C "$F" > /dev/null 2>&1
ARTIST=`$BIN_ID3V2 -l "$F" | sed -e '/TPE1/!d' -e 's/^.*: //g'`
TITLE=`$BIN_ID3V2 -l "$F" | sed -e '/TIT2/!d' -e 's/^.*: //g'`
if [ "$KEEPORIG" -eq "1" ]; then
copy_file "$F" "$ORIGDIR"
fi
# do some checks, check if file already exists and set status
# status will be written to statslog
# depending on status the processing will continue or will skipped to next file
if [[ -z $ARTIST ]] || [[ -z $TITLE ]]
then
logging -e "could not get mp3 tags from source file."
logging -e "ARTIST: $ARTIST / TITLE: $TITLE"
move_file "$F" "$ERRORDIR"
Fstatus="error-notags"
PostExit=1
elif [ -f "$DONEDIR"/"$F" ] || [ -f "$DONEDIR"/"$Fnew" ] ; then
logging -i "File already exists in $DONEDIR ..."
rm "$F"
Fstatus="double-done"
elif [ -f "$OUTPUTDIR"/"$F" ] || [ -f "$OUTPUTDIR"/"$Fnew" ] ; then
logging -i "File already exists in $OUTPUTDIR ..."
rm "$F"
Fstatus="double-output"
elif [ -f "$DONTLIKEDIR"/"$F" ] || [ -f "$DONTLIKEDIR"/"$Fnew" ] ; then
logging -i "I don't like. File exists in $DONTLIKEDIR -> deleting ..."
rm "$F"
Fstatus="dontlike"
fi
# Processing part of loop_fadecut()
writeStats "$ARTIST" "$TITLE" "$GENRE" "$PROFILE" "$Fstatus" "$Fnew"
# skip processing of current file if it is "double" or "don't like"
if [[ $Fstatus != "processing" ]] ; then
continue
fi
splitting "$F" "$ARTIST" "$TITLE" "$GENRE" "$COMMENT"
LENGTH=`$BIN_SOX "$TMPDIR"/"$F" -n stat 2>&1 | grep Length | sed -e 's/.* //' -e 's/\..*//'`
let TRIMLENGTH=$((LENGTH-TRIM_BEGIN-TRIM_END))
let FADE_OUT_START=$((TRIMLENGTH-FADE_OUT))
if [ "$ENCODING" == "mp3" ]; then
mp3Encoding "$F"
fi
if [ "$ENCODING" == "ogg" ]; then
oggEncoding "$F"
fi
if [ "$ENCODING" == "opus" ]; then
opusEncoding "$F"
fi
if [ "$RetLoop" -eq "0" ]; then
logging -s "Ready for listening: $Fdst"
rm "$TMPDIR"/"$F"
rm "$F"
else
move_file "$F" "$ERRORDIR"
# when sox or lame are receiving SIGINT they exit with return-code > 0
# the ctrl_c function does not catch this case, so we have to break here
logging -n "loop_fadecut(): Oops! Something was wrong."
logging -e "loop_fadecut(): returnvalue=$RetLoop"
shutdown_fadecut 3
fi
queueSong
showStats
done
cd "$PWD"
}
list_profiles()
#
# Description: list all existing profiles
#
# Parameter : none
#
# Output : none
#
{
if ls -1 $PROFILEDIR/profiles/* >/dev/null 2>&1
then
for F in $PROFILEDIR/profiles/*
do
echo "$(basename $F) $(grep GENRE $F) $(grep URL $F)"
done
else
logging -e "no profiles found in $PROFILEDIR"
logging -e "create your first profile with 'fadecut -e first-profile'"
fi
return 0
}
load_profile()
#
# Description: loading fadecutrc and profile file
#
# Parameter : none
#
# Output : none
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
if [ ! -r "$PROFILEDIR/profiles/$PROFILE" ]; then
logging -e "Can't not load profile $PROFILEDIR/profiles/$PROFILE"
exit 1
else
logging -i "Loading profile: $PROFILEDIR/profiles/$PROFILE"
. "$PROFILEDIR/profiles/$PROFILE"
fi
check_profile
}
create_profile()
#
# Description: creates a new profile
#
# Parameter : none
#
# Output : none
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
NEW=$1
echo \
"STREAM_URL=\"http://radiostream\"
GENRE=\"YourGenre\"
COMMENT=\"Your Comment\"
# all values in seconds:
FADE_IN=1
FADE_OUT=4
# TRIM_BEGIN=0
# TRIM_END=0" > "$PROFILEDIR/profiles/$NEW"
logging -i "Starting $Editor editor"
$Editor "$PROFILEDIR/profiles/$NEW"
logging -i "Now start: fadecut -r -p $NEW [optional other options]"
}
edit_profile()
#
# Description: edit an existing profile
#
# Parameter : $1 profile name
#
# Output : none
#
{
$Editor "$PROFILEDIR/profiles/$1"
}
check_profile()
#
# Description: check existing profile
# we need all variables to work
#
# Parameter : none
#
# Output : none
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
RetCheckProfile=0
MissingVar=""
if [ -z "$STREAM_URL" ]; then
RetCheckProfile=1
MissingVar="STREAM_URL"
fi
if [ -z "$COMMENT" ]; then
RetCheckProfile=1
MissingVar="COMMENT $MissingVar"
fi
if [ -z "$TRIM_BEGIN" ]; then
RetCheckProfile=1
MissingVar="TRIM_BEGIN $MissingVar"
fi
if [ -z "$TRIM_END" ]; then
RetCheckProfile=1
MissingVar="TRIM_END $MissingVar"
fi
if [ -z "$FADE_IN" ]; then
RetCheckProfile=1
MissingVar="FADE_IN $MissingVar"
fi
if [ -z "$FADE_OUT" ]; then
RetCheckProfile=1
MissingVar="FADE_OUT $MissingVar"
fi
if [ $RetCheckProfile -eq 1 ];
then
logging -e "$PROFILEDIR/profiles/$PROFILE:"
logging -a "$MissingVar not defined"
shutdown_fadecut 1
fi
return 0
}
showStats()
#
# Description: shows file statistics
#
# Parameter : none
#
# Output : none
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
# show statistics only, if all directories are existing
if [ -d "$OUTPUTDIR" ]; then
StatsNewDir=`ls -1 "$OUTPUTDIR" | wc -l`
fi
if [ -d "$ORIGDIR" ]; then
StatsOrigDir=`ls -1 "$ORIGDIR" | wc -l`
fi
if [ -d "$DONEDIR" ]; then
StatsDoneDir=`ls -1 "$DONEDIR" | wc -l`
fi
if [ -d "$DONTLIKEDIR" ]; then
StatsDontlikeDir=`ls -1 "$DONTLIKEDIR" | wc -l`
fi
if [ -d "$ERRORDIR" ]; then
StatsErrorDir=`ls -1 "$ERRORDIR" | wc -l`
fi
if [ -f "$PROFILEDIR"/statslog.csv ]; then
double=$(grep ";double-" "$PROFILEDIR"/statslog.csv | \
grep ";$PROFILE;" | \
cut -d \; -f 4 | \
sort -u | \
wc -l)
processed=$(grep ";processing" "$PROFILEDIR"/statslog.csv | \
grep ";$PROFILE;" | \
cut -d \; -f 4 | \
sort -u | \
wc -l)
fi
logging -a "Output:$StatsNewDir Orig:$StatsOrigDir Done:$StatsDoneDir Dontlike:$StatsDontlikeDir Error:$StatsErrorDir Double:$double Processed:$processed"
}
writeStats()
#
# Description: writes statistics log
#
# Parameter : $1 "artist"
# $2 "title"
# $3 "genre"
# $4 "profile"
# $5 "status"
# $6 "filename"
#
# Usage : writeStats "artist" "title" "genre" "profile" "status" "filename"
#
# Output : none
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
date=`date +%d.%m.%Y`
time=`date +%H:%M:%S`
artist=`echo "$1" | iconv -f ISO-8859-1 -t UTF-8`
title=`echo "$2" | iconv -f ISO-8859-1 -t UTF-8`
genre="$3"
profile="$4"
status="$5"
filename="$6"
echo "$date;$time;$artist;$title;$genre;$profile;$status;$filename" >> "$PROFILEDIR"/statslog.csv
}
oggEncoding()
#
# Description: encoding to ogg
#
# Parameter : $1 filename
#
# Output : none
#
{
if [ $DEBUG -ge 2 ]; then set -x
fi
Fsrc="$*"
Bitrate=$($BIN_MEDIAINFO "$Fsrc" | grep 'Bit rate ' | awk '{ print $4 }')
if [ -z "$Bitrate" ] ; then
Bitrate=128
fi
Fdst=$(filerename $Fsrc)
if [ ! -d "$OUTPUTDIR" ]; then
mkdir -p "$OUTPUTDIR"
fi
# The Bash ‘-o pipefail’ option to set will cause a pipeline to return a
# failure status if any command fails.
set -o pipefail
nice -15 $BIN_SOX -V1 "$TMPDIR"/"$F" -t wav - trim $TRIM_BEGIN $TRIMLENGTH \
silence -l 1 0.5 0.1% -1 0.5 0.1% \
fade t $FADE_IN $FADE_OUT_START $FADE_OUT | \
oggenc - --quiet -b $Bitrate -t "$TITLE" -a "$ARTIST" -G "$GENRE" \
-c "comment=$COMMENT" -o "$OUTPUTDIR"/"$Fdst" || RetLoop=3
# Disable pipefail (default)
set +o pipefail
if [ $VERBOSE -ge 2 ];
then
ogginfo "$OUTPUTDIR"/"$Fdst" || RetLoop=3
fi
}
opusEncoding()
#
# Description: encoding to opus
#
# Parameter : $1 filename
#
# Output : none
#
{
if [ $DEBUG -ge 2 ]; then set -x
fi
Fsrc="$*"
Fdst=$(filerename $Fsrc)
if [ ! -d "$OUTPUTDIR" ]; then
mkdir -p "$OUTPUTDIR"
fi
# The Bash ‘-o pipefail’ option to set will cause a pipeline to return a
# failure status if any command fails.
set -o pipefail
nice -15 $BIN_SOX -V1 "$TMPDIR"/"$F" -t wav - trim $TRIM_BEGIN $TRIMLENGTH \
silence -l 1 0.5 0.1% -1 0.5 0.1% \
fade t $FADE_IN $FADE_OUT_START $FADE_OUT | \
opusenc - --quiet --title "$TITLE" --artist "$ARTIST" --genre "$GENRE" \
--comment "comment=$COMMENT" "$OUTPUTDIR"/"$Fdst" || RetLoop=3
# Disable pipefail (default)
set +o pipefail
if [ $VERBOSE -ge 2 ];
then
opusinfo "$OUTPUTDIR"/"$Fdst" || RetLoop=3
fi
}
mp3Encoding()
#
# Description: encoding to mp3
#
# Parameter : $1 filename
#
# Output : none
#
{
if [ $DEBUG -ge 2 ]; then set -x
fi
Fsrc="$*"
Bitrate=$($BIN_MEDIAINFO "$Fsrc" | grep 'Bit rate ' | awk '{ print $4 }')
if [ -z "$Bitrate" ] ; then
Bitrate=128
fi
Fdst=$(filerename $Fsrc)
if [ ! -d "$OUTPUTDIR" ]; then
mkdir -p "$OUTPUTDIR"
fi
# The Bash ‘-o pipefail’ option to set will cause a pipeline to return a
# failure status if any command fails.
set -o pipefail
nice -15 $BIN_SOX -V1 "$TMPDIR"/"$Fsrc" -t wav - trim $TRIM_BEGIN $TRIMLENGTH \
silence -l 1 0.5 0.1% -1 0.5 0.1% \
fade t $FADE_IN $FADE_OUT_START $FADE_OUT | \
lame --quiet -b $Bitrate --add-id3v2 --ta "$ARTIST" --tt "$TITLE" \
--tg "$GENRE" --tc "$COMMENT" - "$OUTPUTDIR"/"$Fdst" || RetLoop=3
# Disable pipefail (default)
set +o pipefail
# delete tag written by lame (TLEN is always the same and always wrong)
# found with LAME 32bits version 3.98.4
# this patch was made after a feedback of Jonas Schmid
$BIN_ID3V2 --TLEN "" "$OUTPUTDIR"/"$Fdst"
}
splitting()
#
# Description: split files using silence detection of sox
#
# Parameter : $1 filename
# $2 "artist"
# $3 "title"
# $4 "genre"
# $5 "comment"
#
# Output : none
#
{
F="$1"
ARTIST="$2"
TITLE="$3"
GENRE="$4"
COMMENT="$5"
$BIN_SOX -V1 "$F" -t wav "$TMPDIR"/"$F".wav silence 1 0.50 0.1% 1 0.5 0.1% : newfile : restart
Fcount=`ls -1 "$TMPDIR"/"$F"* | wc -l`
#choose biggest file of sox output as we think this will be the wanted main part
Ftmp=`ls -1S "$TMPDIR"/"$F"* | sed -e 's/.*\///g' | head -1`
mv "$TMPDIR"/"$Ftmp" "$TMPDIR"/"$F"
if [ $Fcount -ge 2 ] ; then
logging -i "sox found silence and splitted..."
rm "$TMPDIR"/"$F"00*
Fnew=$(filerename $F)
writeStats "$ARTIST" "$TITLE" "$GENRE" "$PROFILE" "soxsplit into $Fcount files" "$Fnew"
fi
return 0
}
filerename()
#
# Description: rename filenames
#
# Parameter : $1 old filename
#
# Output : new filename
#
{
if [ $DEBUG -ge 2 ]; then set -x
fi
Fnold="$*"
# Change destination filename according to selected $ENCODING
local tmp=$(echo $Fnold | sed -e "s/\.mp3/\.$ENCODING/g")
Fnnew=$(echo $tmp | sed -e 's/ /_/g' -e 's/\(.*\)/\L\1/')
echo $Fnnew
return 0
}
checkRequirements()
#
# Description: Check if all necessary tools and binaries are available
#
# Parameter : none
#
# Output : logging
# forces an error if a needed binary is not available
#
{
if [ $DEBUG -ge 3 ]; then set -x
fi
logging -d "Checking fadecut requirements"
if [ -z $BIN_STREAMRIPPER ]; then RequirementsMsg=streamripper
fi
if [ -z $BIN_SOX ]; then RequirementsMsg=sox
fi
if [ -z $BIN_ID3V2 ]; then RequirementsMsg=id3v2
fi
if [ -z $BIN_MEDIAINFO ]; then RequirementsMsg=mediainfo
fi
if [ "$ENCODING" == "ogg" ];
then
if [ -z $BIN_OGGINFO ]; then RequirementsMsg=ogginfo
fi
if [ -z $BIN_OGGENC ]; then RequirementsMsg=oggenc
fi
fi
if [ "$ENCODING" == "opus" ];
then
if [ -z $BIN_OPUSINFO ]; then RequirementsMsg=opusinfo
fi
if [ -z $BIN_OPUSENC ]; then RequirementsMsg=opusenc
fi
fi
if [ "$ENCODING" == "mp3" ];
then
if [ -z $BIN_LAME ]; then RequirementsMsg=lame
fi
fi
if [ ! -z $RequirementsMsg ];
then
logging -e "Program $RequirementsMsg not installed or not in PATH"
return 1
fi
if [ ! -w "$WORKDIR" ];
then
logging -e "Cannot write into $WORKDIR directory"
return 1
fi
return 0
}
copy_file()
#
# Description: checks if directory exists, creates it if necessary and copy file to it
#
# Parameter : $1 file
# $2 destination directory
#
# Output : none
#
{
if [ $DEBUG -ge 2 ]; then set -x
fi
if [ ! -d "$2" ]; then
mkdir -p "$2"
fi
cp "$1" "$2"
return 0
}
move_file()
#
# Description: checks if directory exists, creates it if necessary and moves file to it
#
# Parameter : $1 file
# $2 destination directory
#
# Output : none
#
{
if [ $DEBUG -ge 2 ]; then set -x
fi
if [ ! -d "$2" ]; then
mkdir -p "$2"
fi
mv "$1" "$2"
return 0
}
set_options()
#
# Description: set variables according to commandline settings
#
# Parameter : none
#
# Output : none
#
{
if [ ! -z "$GETOPT_DEBUG" ] ; then
DEBUG=$GETOPT_DEBUG
fi
if [ ! -z "$GETOPT_VERBOSE" ] ; then
VERBOSE=$GETOPT_VERBOSE
fi
if [ ! -z "$GETOPT_KEEPORIG" ] ; then
KEEPORIG=$GETOPT_KEEPORIG
fi
if [ ! -z "$GETOPT_WORKDIR" ]; then
WORKDIR=$GETOPT_WORKDIR
fi
if [ ! -z "$GETOPT_OUTPUTDIR" ]; then
OUTPUTDIR=$GETOPT_OUTPUTDIR
fi
if [ ! -z "$GETOPT_STREAMRIPPER_START" ]; then
STREAMRIPPER_START=$GETOPT_STREAMRIPPER_START
fi
}
# Main ------------------------------------------------------------------------
# trap keyboard interrupt (control-c)
trap control_c SIGINT
# create profile directory if it does not already exist
createDirs
# When you need an argument that needs a value, you put the ":" right after
# the argument in the optstring. If your var is just a flag, withou any
# additional argument, just leave the var, without the ":" following it.
#
# please keep letters in alphabetic order
#
while getopts ":c:d:e:hi:klo:p:qrv" OPTION
do
case $OPTION in
c)
create_profile $OPTARG
exit 0
;;
d)
GETOPT_DEBUG=$OPTARG
;;
e)
edit_profile $OPTARG
exit 0
;;
h)
usage
exit 1
;;
i)
GETOPT_WORKDIR=$(readlink -f $OPTARG)
;;
k)
GETOPT_KEEPORIG=1 # keep original files
;;
l)
list_profiles
exit 0
;;
o)
GETOPT_OUTPUTDIR=$(readlink -f $OPTARG)
;;
p)
PROFILE=$OPTARG
;;
q)
GETOPT_VERBOSE=0
# add LOGGING variable and change logging function to be able to turn
# all output off
;;
r)
GETOPT_STREAMRIPPER_START=1
;;
v)
GETOPT_VERBOSE=1
;;
\?)
logging -e "Invalid option: -$OPTARG" >&2
usage
shutdown_fadecut 1
;;
:)
logging -e "Option -$OPTARG requires an argument." >&2
shutdown_fadecut 1
;;
esac
done
# CheckRequirements before do anything
if ! checkRequirements; then shutdown_fadecut 1
fi
# set_options first, to be quiet or verbose
set_options
# load master profile
if [ -r "$PROFILEDIR/fadecutrc" ]; then
logging -i "Loading master profile: $PROFILEDIR/fadecutrc"
. "$PROFILEDIR/fadecutrc"
fi
# set_options again, to override predefined settings from master profile with commandline settings
set_options
# load profile first, so we are able to define profile specific settings
if [ -z $PROFILE ] ; then
usage
exit 1
else
load_profile
fi
# set_options again, to override predefined settings from profiles with commandline settings
set_options
# set working directory AFTER loading profile to be able to override settings with commandline parameters
if [ ! -d "$WORKDIR" ]; then
logging -e "$WORKDIR: Input directory does not exist"
shutdown_fadecut 3
else
logging -n "Using for input: $WORKDIR"
fi
# set output directory AFTER loading profile to be able to override settings with commandline parameters
if [ ! -d "$OUTPUTDIR" ]; then
logging -e "$OUTPUTDIR: Output directory does not exist"
shutdown_fadecut 3
else
logging -n "Using for output: $OUTPUTDIR"
fi
# check if directory settings are ok
if [ "$OUTPUTDIR" = "$WORKDIR" ]; then
logging -e "Output and input directory can not be equal!"
usage
exit 1
fi
StreamInfo=""
StreamInfo2=""
while true
do
startStream
loop_fadecut
logging -n "Main(): Loop until we're finished"
sleep 2
# if streamripper is working then show info about it
if [ $STREAMRIPPER_START == "1" ] && [ -f $LOGDIR/fadecutstream-$PID.log ];
then
StreamStatus=$(tail $LOGDIR/fadecutstream-$PID.log | grep error)
if [ -z "$StreamStatus" ] ; then
StreamInfo=$(tail -1 $LOGDIR/fadecutstream-$PID.log | sed -e 's/ \[.*$//g')
if [ "$StreamInfo" != "$StreamInfo2" ] ; then
logging -r "$StreamInfo"
StreamInfo2="$StreamInfo"
fi
else
logging -e "Streamripper exited with $StreamStatus"
rm $LOGDIR/fadecutstream-$PID.log
exit 1
fi
sleep $LOOP_INTERVAL
fi
done