#!/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 results="${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_ROWID();' >&3 read -u 4 results results="${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 results="${results#* = }" echo "$results" } getFiles() { : } getType() { : } getInfos::MP3() { : } getInfos::Ogg() { : } getInfos::FLAC() { : } getInfos::MPC() { : } getTags() { #getType #getInfos:: : } 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 <