AtOM/atom
2013-02-25 15:51:34 +01:00

552 lines
9.5 KiB
Bash
Executable File

#!/bin/bash
## Define exit codes
# General config errors [10-19]
ELOAD=10
EINTERVAL=11
ENOCFG=19
# Source cofig errors [20-29]
# Destination config errors [30-49]
EFORMAT=30
ECHANNEL=31
EFMTINVPARM=49
# config structures
declare -A \
destinationchannels \
destinationcopymime \
destinationformat \
destinationfrequency \
destinationpath \
destinationquality \
destinationrename \
destinationrenamepath \
destinationskipmime \
|| {
echo "Check your Bash version. You need >= 4.0" >&2
exit $EBASHVERS
}
DOCDIR=./doc
SHAREDIR=./share
exampleconf=$DOCDIR/example.cfg
schema=$SHAREDIR/schema.sql
#parse arguments
#parse config
getConfigGeneral() {
case $key in
'max-load')
expr='^[0-9]*$'
if [[ $value =~ $expr ]]
then
maxload="$value"
else
echo "Invalid max-load value: $value" >&2
exit $ELOAD
fi
unset expr
;;
'load-interval')
expr='^[0-9]*$'
if [[ $value =~ $expr ]]
then
loadinterval="$value"
else
echo "Invalid load-interval value: $value" >&2
exit $EINTERVAL
fi
unset expr
;;
'temporary-directory')
tempdir="$value"
;;
'database')
database="$value"
;;
debug)
#unimplemented
;;
esac
}
getConfigSource() {
case "$key" in
'path')
sourcepath="$value"
;;
'id3charset')
sourceid3charset="$value"
;;
esac
}
getConfigDestination() {
case "$key" in
'path')
destinationpath["$destination"]="$value"
;;
'format')
case "$value" in
'mp3')
destinationformat["$destination"]=mp3
;;
'vorbis')
destinationformat["$destination"]=vorbis
;;
*)
echo "Unsupported destination format: $value" >2&
exit $EFORMAT
;;
esac
;;
'quality')
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then
echo "Invalid quality value: $value" >&2
exit $EQUALITY
fi
unset expr
case "${destinationformat["$destination"]}" in
'vorbis')
destinationquality["$destination"]="$value"
;;
*)
echo "$Invalid parameter \"$key\" for format \"${destinationformat["$destination"]}\"" >&2
exit $EFMTINVPARM
;;
esac
;;
'bitrate')
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then
echo "Invalid bitrate value: $value" >&2
exit $EQUALITY
fi
unset expr
case "${destinationformat["$destination"]}" in
'mp3')
destinationquality["$destination"]="$value"
;;
*)
echo "$Invalid parameter \"$key\" for format \"${destinationformat["$destination"]}\"" >&2
exit $EFMTINVPARM
;;
esac
;;
'channels')
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then
echo "Invalid channel count: $value" >&2
exit $ECHANNEL
fi
unset expr
destinationchannels["$destination"]=$value
;;
'frequency')
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then
echo "Invalid frequency value: $value" >&2
exit $ECHANNEL
fi
unset expr
destinationfrequency["$destination"]=$value
;;
'rename')
case "$value" in
*/*)
destinationrenamepath["$destination"]="${value%/*}"
;;
esac
destinationrename["$destination"]="${value##*/}"
;;
'skip_mime-type')
destinationskipmime[$destination]="${destinationskipmime[$destination]:+${destinationskipmime[$destination]}|}$value"
;;
'copy_mime-type')
destinationcopymime[$destination]="${destinationcopymime[$destination]:+${destinationcopymime[$destination]}|}$value"
;;
esac
}
getConfig() {
while read key value
do
case $key in
'#'*)
#comment
;;
'')
#empty line
;;
'[general]')
context=General
;;
'[source]')
context=Source
;;
\[*\])
context=Destination
destination="${key#[}"
destination="${destination%]}"
;;
*)
getConfig$context
;;
esac
done < ~/.atom/atom.cfg
}
#check sanity
openDatabase() {
if [ ! -d "$tempdir" ]
then
mkdir -p "$tempdir"
fi
mkfifo "$tempdir"/sqlite.{in,out}
if [ ! -f "$database" ]
then
if [ ! -d "${database%/*}" ]
then
mkdir -p "${database%/*}"
fi
sqlite3 "$database" < $schema
fi
sqlite3 -line "$database" \
< "$tempdir/sqlite.in" \
> "$tempdir/sqlite.out" &
exec 3> "$tempdir"/sqlite.in
exec 4< "$tempdir"/sqlite.out
}
closeDatabase() {
exec 3>&-
exec 4<&-
rm "$tempdir"/sqlite.{in,out}
}
Select() {
#Select table [col1 [col2 [..]]] < WHERE_key WHERE_value
# [WHERE_key WHERE_value
# […]]
local \
table="$1" \
col \
columns \
results \
where_statement
shift
for col
do
(( ${#columns} )) && columns+=','
columns+="$col"
done
while read key value
do
(( ${#where_statement} )) && where_statement+=( "AND" )
if [[ $value == NULL ]]
then
where_statement+=( "$key is NULL" )
else
where_statement+=( "$key='$value'" )
fi
done
echo "SELECT IFNULL(" \
"(SELECT $columns FROM $table" \
"WHERE ${where_statement[@]})" \
",'SQL::Select:not found'" \
");" >&3
read -u 4 results
if ! [[ $results == "SQL::Select:not found" ]]
then
echo "$results"
else
return 1
fi
}
Insert() {
#Insert table [no_id] < key value
# [key value
# […]]
local \
table="$1" \
no_id="${2:-0}" \
insert_keys \
insert_values \
results
while read key value
do
(( ${#insert_keys} )) && insert_keys+=","
insert_keys+='`'"$key"'`'
(( ${#insert_values} )) && insert_values+=","
if [[ $value == NULL ]]
then
insert_values+="NULL"
else
insert_values+='"'"${value//\"/\\\"}"'"'
fi
done
echo "INSERT INTO $table" \
"( $insert_keys )" \
"VALUES" \
"( $insert_values );" >&3
(( no_id )) || {
echo 'SELECT LAST_INSERT_ID();' >&3
read -u 4 results
echo "$results"
}
}
Update(){
#Update table set_key set_value [set_key set_value […]] < where_key where_value
# [where_key where_value
# […]]
local \
table="$1" \
key \
argument \
value \
set_statement \
where_keys \
where_values \
what \
where_statement \
results
shift
what=key
for argument
do
case $what in
key)
set_statement="${set_statement:+${set_statement+,}}\`$argument\`"
what=value
;;
value)
set_statement="${set_statement}='$argument'"
what=key
;;
esac
done
while read key value
do
(( ${#where_statement} )) && where_statement+=( "AND" )
if [[ $value == NULL ]]
then
where_statement+=( "$key is NULL" )
else
where_statement+=( "$key='$value'" )
fi
done
echo "UPDATE '$table' SET" \
"$set_statement" \
"WHERE" \
"${where_statement[@]}" \
";" >&3
}
InsertOrUpdate() {
#InsertOrUpdate table set_key set_value [set_key set_value […]] < where_key where_value
# [where_key where_value
# […]]
local \
table="$1" \
argument \
key \
keys \
set_keys \
set_values \
value \
values \
what \
results
shift
what=key
for argument
do
case $what in
key)
set_keys+=( "$argument" )
what=value
;;
value)
set_values+=( "$argument" )
what=key
;;
esac
done
while read key value
do
keys+=( "$key" )
values+=( "$value" )
done
if results=$(
Select "$table" id < <(
for key in ${!keys[@]}
do
echo "${keys[$key]}" "${values[$key]}"
done
)
)
then
Update "$table" "$@" < <(
for key in ${!keys[@]}
do
echo "${keys[$key]}" "${values[$key]}"
done
)
else
results=$(
Insert "$table" < <(
for key in ${!set_keys[@]}
do
echo "${set_keys[$key]}" "${set_values[$key]}"
done
for key in ${!keys[@]}
do
echo "${keys[$key]}" "${values[$key]}"
done
)
)
fi
echo "$results"
}
getFiles() {
:
}
getType() {
:
}
getInfos::MP3() {
:
}
getInfos::Ogg() {
:
}
getInfos::FLAC() {
:
}
getInfos::MPC() {
:
}
getTags() {
#getType
#getInfos::<type>
:
}
encodeFile::MP3() {
#lame
:
}
encodeFile::Ogg() {
#oggenc
:
}
transcodeFile() {
#sox -> wav
for format in $targets["format"]
do
#encodeFile::$format
:
done
#signal and of encoding to parent
}
checkFinished() {
#retrieve info from finished transcodeFile()
#update counters / metadata
:
}
checkLoad() {
#if load > threshold
# decrease concurrency
#elif load < threshold
# increase concurrency
#fi
:
}
readUserInput() {
#read + / - / q(uit) / p(ause)
#initiate shutdown / check load threshold / SIGSTOP all children / SIGCONT all children
:
}
transcodeLauncher() {
checkLoad
checkFinished
#until running processes < max processes
#do
checkLoad
checkFinished
readUserInput
#done
transcodeFile &
#update counter / metadata
}
#UI
if [ ! -f ~/.atom/atom.cfg ]
then
if [ ! -d ~/.atom ]
then
mkdir -p ~/.atom
fi
sed "s/%HOME%/$HOME/" "$exampleconf" ~/.atom/atom.cfg
cat >&2 <<-EOCfgNotice
No configuration file found!
An example file has been created as ~/.atom/atom.cfg.
You should change it to your likings using you favorite editor.
Bailing out.
EOCfgNotice
exit $ENOCFG
fi
getConfig
{
cat <<EOF
General|Load|$maxload
|Load Interval|$loadinterval
|Temp Dir|$tempdir
|Database|$database
|Debug|$debug
Source|Path|$sourcepath
|ID3 Charset|$sourceid3charset
EOF
for destination in ${!destinationpath[@]}
do
cat <<EOF
$destination|Path|${destinationpath[$destination]}
|Format|${destinationformat[$destination]}
|Quality|${destinationquality[$destination]}
|Channels|${destinationchannels[$destination]}
|Frequency|${destinationfrequency[$destination]}
|Path Change|${destinationrenamepath[$destination]}
|File Rename|${destinationrename[$destination]}
EOF
echo "|Skipped mime-type|${destinationskipmime[$destination]//\|/
|Skipped mime-type|}"
echo "|Copied mime-type|${destinationcopymime[$destination]//\|/
|Copied mime-type|}"
done
}|column -t -s'|' -n
openDatabase
closeDatabase
# vim:set ts=8 sw=8: