Merge branch 'split'
This commit is contained in:
commit
d3c46516a8
@ -26,6 +26,8 @@ Sections:
|
||||
too quickly. Set this too high, and AtOM will not adapt quickly enough to
|
||||
load increase. In both cases, your hard drive will suffer. In my
|
||||
experience, 30 seconds is a good value.
|
||||
* ionice <class> [niceness]: IO-hungry processes will be run with ionice class
|
||||
<class> and niceness [niceness] (if applicable). See man ionice for details.
|
||||
* temporary-directory <directory>: String. Name speaks for itself: this is
|
||||
where FIFOs (for communicating with sqlite) and temporary WAVE files will
|
||||
be created. Note that debug logs (if enabled) will go there too.
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
[general]
|
||||
ionice 3
|
||||
max-load 6
|
||||
load-interval 30
|
||||
temporary-directory %HOME%/.atom/tmp
|
||||
|
||||
28
lib/config/getConfig
Normal file
28
lib/config/getConfig
Normal file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
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 < "$cffile"
|
||||
}
|
||||
171
lib/config/getConfigDestination
Normal file
171
lib/config/getConfigDestination
Normal file
@ -0,0 +1,171 @@
|
||||
#!/bin/bash
|
||||
getConfigDestination() {
|
||||
case "$key" in
|
||||
'path')
|
||||
destinationpath["$destination"]="$value"
|
||||
;;
|
||||
'format')
|
||||
case "$value" in
|
||||
'mp3')
|
||||
destinationformat["$destination"]=mp3
|
||||
;;
|
||||
'opus')
|
||||
destinationformat["$destination"]=opus
|
||||
;;
|
||||
'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
|
||||
;;
|
||||
'normalize')
|
||||
case $value in
|
||||
'true'|'on'|'yes')
|
||||
destinationnormalize["$destination"]=1
|
||||
;;
|
||||
'false'|'off'|'no')
|
||||
destinationnormalize["$destination"]=0
|
||||
;;
|
||||
*)
|
||||
echo "normalize takes values:" \
|
||||
"'yes' ,'true' ,'on', 'no', 'false',"\
|
||||
"'off'"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
'bitrate')
|
||||
expr='^[0-9]*$'
|
||||
if ! [[ $value =~ $expr ]]
|
||||
then
|
||||
echo "Invalid bitrate value: $value" >&2
|
||||
exit $EQUALITY
|
||||
fi
|
||||
unset expr
|
||||
case "${destinationformat["$destination"]}" in
|
||||
'opus')
|
||||
destinationquality["$destination"]="$value"
|
||||
;;
|
||||
'mp3')
|
||||
destinationquality["$destination"]="$value"
|
||||
;;
|
||||
*)
|
||||
echo "$Invalid parameter \"$key\" for format \"${destinationformat["$destination"]}\"" >&2
|
||||
exit $EFMTINVPARM
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
'loss')
|
||||
expr='^[0-9]*$'
|
||||
if ! [[ $value =~ $expr ]]
|
||||
then
|
||||
echo "Invalid loss value: $value" >&2
|
||||
exit $EQUALITY
|
||||
fi
|
||||
unset expr
|
||||
case "${destinationformat["$destination"]}" in
|
||||
'opus')
|
||||
destinationloss["$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
|
||||
;;
|
||||
'noresample')
|
||||
case $value in
|
||||
'true'|'on'|'yes')
|
||||
destinationnoresample["$destination"]=1
|
||||
;;
|
||||
'false'|'off'|'no')
|
||||
destinationnoresample["$destination"]=0
|
||||
;;
|
||||
*)
|
||||
echo "noresample takes values:" \
|
||||
"'yes' ,'true' ,'on', 'no', 'false',"\
|
||||
"'off'"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
'rename')
|
||||
case "$value" in
|
||||
*/*)
|
||||
destinationrenamepath["$destination"]="${value%/*}"
|
||||
;;
|
||||
esac
|
||||
destinationrename["$destination"]="${value##*/}"
|
||||
;;
|
||||
'fat32compat')
|
||||
case $value in
|
||||
'true'|'on'|'yes')
|
||||
destinationfat32compat["$destination"]=1
|
||||
;;
|
||||
'false'|'off'|'no')
|
||||
destinationfat32compat["$destination"]=0
|
||||
;;
|
||||
*)
|
||||
echo "fat32compat takes values:" \
|
||||
"'yes' ,'true' ,'on', 'no', 'false',"\
|
||||
"'off'"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
'skip_mime-type')
|
||||
destinationskipmime[$destination]="${destinationskipmime[$destination]:+${destinationskipmime[$destination]}|}$value"
|
||||
;;
|
||||
'copy_mime-type')
|
||||
destinationcopymime[$destination]="${destinationcopymime[$destination]:+${destinationcopymime[$destination]}|}$value"
|
||||
;;
|
||||
'higher-than')
|
||||
expr='^[0-9]*$'
|
||||
if ! [[ $value =~ $expr ]]
|
||||
then
|
||||
echo "Invalid higher-than bitrate value: $value" >&2
|
||||
exit $EMAXBPS
|
||||
fi
|
||||
unset expr
|
||||
destinationmaxbps[$destination]="$value"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
79
lib/config/getConfigGeneral
Normal file
79
lib/config/getConfigGeneral
Normal file
@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
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
|
||||
;;
|
||||
'ionice')
|
||||
read class niceness <<<"$value"
|
||||
case $class in
|
||||
1)
|
||||
# real-time class, only root can do that
|
||||
if (( UID ))
|
||||
then
|
||||
echo "IO class 'realtime' is"\
|
||||
"not available to unprivileged"\
|
||||
"users" >&2
|
||||
exit $EIONICE
|
||||
fi
|
||||
if [ -n "$niceness" ] \
|
||||
&& (( niceness >= 0 && niceness <= 7 ))
|
||||
then
|
||||
ionice="ionice -c1 -n$niceness "
|
||||
else
|
||||
echo "Invalid IO priority"\
|
||||
"'$niceness'" >&2
|
||||
exit $EIONICE
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
if [ -n "$niceness" ] \
|
||||
&& (( niceness >= 0 && niceness <= 7 ))
|
||||
then
|
||||
ionice="ionice -c2 -n$niceness "
|
||||
else
|
||||
echo "Invalid IO priority"\
|
||||
"'$niceness'" >&2
|
||||
exit $EIONICE
|
||||
fi
|
||||
;;
|
||||
3)
|
||||
ionice="ionice -c3 "
|
||||
;;
|
||||
*)
|
||||
echo "Invalid ionice parameters $value"\
|
||||
>&2
|
||||
exit $EIONICE
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
'temporary-directory')
|
||||
tempdir="$value"
|
||||
;;
|
||||
'database')
|
||||
database="$value"
|
||||
;;
|
||||
debug)
|
||||
(( value > debug )) && debug=$value
|
||||
;;
|
||||
esac
|
||||
}
|
||||
11
lib/config/getConfigSource
Normal file
11
lib/config/getConfigSource
Normal file
@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
getConfigSource() {
|
||||
case "$key" in
|
||||
'path')
|
||||
sourcepath="$value"
|
||||
;;
|
||||
'skip')
|
||||
skippeddirectories+=( "$value" )
|
||||
;;
|
||||
esac
|
||||
}
|
||||
54
lib/config/print
Normal file
54
lib/config/print
Normal file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
printConfig() {
|
||||
{
|
||||
echo "General|Config file|$cffile"
|
||||
[ -n "$ionice" ] && echo "|IO Nice|$ionice"
|
||||
cat <<-EOF
|
||||
|Load|$maxload
|
||||
|Load Interval|$loadinterval
|
||||
|Temp Dir|$tempdir
|
||||
|Database|$database
|
||||
|Debug|$debug
|
||||
Source|Path|$sourcepath
|
||||
EOF
|
||||
for prune_expression in "${skippeddirectories[@]}"
|
||||
do
|
||||
(( printed )) \
|
||||
&& echo -n '||' \
|
||||
|| echo -n '|Skipped directories|'
|
||||
echo "$prune_expression"
|
||||
printed=1
|
||||
done
|
||||
unset printed
|
||||
for destination in ${!destinationpath[@]}
|
||||
do
|
||||
cat <<-EOF
|
||||
$destination|Path|${destinationpath["$destination"]}
|
||||
|Format|${destinationformat["$destination"]}
|
||||
|Quality|${destinationquality["$destination"]}
|
||||
EOF
|
||||
if [[ ${destinationformat["$destination"]} == opus ]]
|
||||
then
|
||||
echo "|Expected loss|${destinationloss["$destination"]}"
|
||||
elif [[ ${destinationformat["$destination"]} == mp3 ]]
|
||||
then
|
||||
echo "|Prevent resampling|${destinationnoresample["$destination"]}"
|
||||
fi
|
||||
cat <<-EOF
|
||||
|Normalize|${destinationnormalize["$destination"]}
|
||||
|Channels|${destinationchannels["$destination"]}
|
||||
|Frequency|${destinationfrequency["$destination"]}
|
||||
|Higher than|${destinationmaxbps["$destination"]}
|
||||
|Fat32 Compat.|${destinationfat32compat["$destination"]}
|
||||
|Path Change|${destinationrenamepath["$destination"]}
|
||||
|File Rename|${destinationrename["$destination"]}
|
||||
EOF
|
||||
[ -n "${destinationskipmime["$destination"]}" ] \
|
||||
&& echo "|Skipped mime-types|${destinationskipmime["$destination"]//\|/
|
||||
||}"
|
||||
[ -n "${destinationmskipime["$destination"]}" ] \
|
||||
&& echo "|Copied mime-types|${destinationcopymime["$destination"]//\|/
|
||||
||}"
|
||||
done
|
||||
}|column -t -s'|' -n
|
||||
}
|
||||
19
lib/copy/checkCopy
Normal file
19
lib/copy/checkCopy
Normal file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
checkCopy() {
|
||||
(
|
||||
[ -z "${destinationfrequency[$destination]}" ] \
|
||||
|| (( ${rate:-0} == ${destinationfrequency[$destination]} ))
|
||||
) && (
|
||||
[ -z "${destinationchannels[$destination]}" ] \
|
||||
|| (( ${channels:-0} == ${destinationchannels[$destination]} ))
|
||||
) && (
|
||||
(( ${bitrate:-1000} == ${destinationquality[$destination]} )) \
|
||||
|| (
|
||||
[ -n "${destinationmaxbps[$destination]}" ] \
|
||||
|| ((
|
||||
${bitrate:-1000}
|
||||
<= ${destinationmaxbps[$destination]:-0}
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
74
lib/copy/copyFiles_action
Normal file
74
lib/copy/copyFiles_action
Normal file
@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
copyFiles_action() {
|
||||
echo '
|
||||
SELECT
|
||||
source_files.filename,
|
||||
source_files.last_change,
|
||||
destinations.id,
|
||||
destination_files.id
|
||||
FROM source_files
|
||||
INNER JOIN destination_files
|
||||
ON source_files.id
|
||||
= destination_files.source_file_id
|
||||
INNER JOIN destinations
|
||||
ON destination_files.destination_id=destinations.id
|
||||
INNER JOIN mime_type_actions
|
||||
ON mime_type_actions.id = source_files.mime_type
|
||||
WHERE CAST(destination_files.last_change AS TEXT)
|
||||
<> CAST(source_files.last_change AS TEXT)
|
||||
AND mime_type_actions.destination_id = destinations.id
|
||||
AND mime_type_actions.action = 2;
|
||||
|
||||
SELECT "AtOM:NoMoreFiles";' >&3
|
||||
read -u4 line
|
||||
while ! [[ $line = AtOM:NoMoreFiles ]]
|
||||
do
|
||||
copyfiles+=("$line")
|
||||
read -u4 line
|
||||
done
|
||||
|
||||
for copyfile in "${copyfiles[@]}"
|
||||
do
|
||||
sourcefilename=${copyfile%%|*}
|
||||
rest="${copyfile#*|}|"
|
||||
lastchange=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
destinationid=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
destfileid=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
echo 'SELECT IFNULL( (
|
||||
SELECT destination_files.filename
|
||||
FROM destination_files
|
||||
INNER JOIN source_files
|
||||
ON destination_files.source_file_id=source_files.id
|
||||
INNER JOIN mime_type_actions
|
||||
ON
|
||||
mime_type_actions.id=source_files.mime_type
|
||||
INNER JOIN destinations
|
||||
ON destinations.id=destination_files.destination_id
|
||||
WHERE destinations.id = '$destinationid'
|
||||
AND source_files.filename LIKE "'"${sourcefilename%/*}"'/%"
|
||||
AND mime_type_actions.action = 1
|
||||
LIMIT 1
|
||||
),"AtOM:NotFound");
|
||||
'>&3
|
||||
read -u4 filename
|
||||
if [[ $filename != AtOM:NotFound ]]
|
||||
then
|
||||
destdir=${filename%/*}
|
||||
if cp -al "$sourcepath/$sourcefilename" "$destdir" 2>/dev/null\
|
||||
|| cp -a "$sourcepath/$sourcefilename" "$destdir"
|
||||
then
|
||||
Update destination_files \
|
||||
filename "$destdir/${sourcefilename##*/}"\
|
||||
rename_pattern "${destinationrenamepath[$destination]}/${destinationrename[$destination]}:${destinationfat32compat["$destination"]}"\
|
||||
<<-EOWhere
|
||||
id = $destfileid
|
||||
last_change = $lastchange
|
||||
EOWhere
|
||||
progressSpin
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
29
lib/copy/copyFiles_matching
Normal file
29
lib/copy/copyFiles_matching
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
copyFiles_matching() {
|
||||
extension="${filename##*.}"
|
||||
cp -al \
|
||||
"$sourcepath/$filename" \
|
||||
"$destdir/$destfile.$extension" \
|
||||
2>/dev/null \
|
||||
|| cp -a \
|
||||
"$sourcepath/$filename" \
|
||||
"$destdir/$destfile.$extension"
|
||||
echo \
|
||||
"UPDATE destination_files" \
|
||||
"SET filename=\"${filename//\"/\"\"}\"," \
|
||||
" last_change=(" \
|
||||
" SELECT last_change" \
|
||||
" FROM source_files" \
|
||||
" WHERE id=$fileid" \
|
||||
" )," \
|
||||
" old_filename=(" \
|
||||
" SELECT filename" \
|
||||
" FROM destination_files" \
|
||||
" WHERE id=$destfileid" \
|
||||
" )," \
|
||||
" rename_pattern=" \
|
||||
"\"${destinationrenamepath[$destination]}/${destinationrename[$destination]}:${destinationfat32compat["$destination"]}\""\
|
||||
"WHERE id=$destfileid;" \
|
||||
>&3
|
||||
(( ++copies ))
|
||||
}
|
||||
24
lib/database/Delete
Normal file
24
lib/database/Delete
Normal file
@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
Delete() {
|
||||
#Delete table < where_key where_operator where_value
|
||||
# [where_key where_operator where_value
|
||||
# […]]
|
||||
local \
|
||||
table="$1" \
|
||||
key \
|
||||
operator \
|
||||
value \
|
||||
where_statement \
|
||||
results
|
||||
while read key operator value
|
||||
do
|
||||
(( ${#where_statement} )) && where_statement+=( "AND" )
|
||||
if [[ $value == NULL ]]
|
||||
then
|
||||
where_statement+=( "$key is NULL" )
|
||||
else
|
||||
where_statement+=( "$key $operator "'"'"${value//\"/\"\"}"'"' )
|
||||
fi
|
||||
done
|
||||
echo "DELETE from $table WHERE ${where_statement[@]};" >&3
|
||||
}
|
||||
38
lib/database/Insert
Normal file
38
lib/database/Insert
Normal file
@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
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+=","
|
||||
case $value in
|
||||
'NULL')
|
||||
insert_values+="NULL"
|
||||
;;
|
||||
+([0-9])?(.+([0-9])))
|
||||
insert_values+=$value
|
||||
;;
|
||||
*)
|
||||
insert_values+='"'"${value//\"/\"\"}"'"'
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo "INSERT INTO $table" \
|
||||
"( $insert_keys )" \
|
||||
"VALUES" \
|
||||
"( $insert_values );" >&3
|
||||
(( no_id )) || {
|
||||
echo 'SELECT LAST_INSERT_ROWID();' >&3
|
||||
read -u 4 results
|
||||
echo "$results"
|
||||
}
|
||||
}
|
||||
43
lib/database/InsertIfUnset
Normal file
43
lib/database/InsertIfUnset
Normal file
@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
InsertIfUnset() {
|
||||
#InsertIfUnset table [no_id] < key value \n key value
|
||||
local \
|
||||
table="$1" \
|
||||
no_id="${2:-0}" \
|
||||
column \
|
||||
key \
|
||||
keys \
|
||||
results \
|
||||
value \
|
||||
values
|
||||
while read key value
|
||||
do
|
||||
keys+=( "$key" )
|
||||
values+=( "$value" )
|
||||
done
|
||||
if (( no_id ))
|
||||
then
|
||||
column="${keys[0]}"
|
||||
else
|
||||
column='id'
|
||||
fi
|
||||
if ! results=$(
|
||||
Select "$table" "$column" < <(
|
||||
for key in ${!keys[@]}
|
||||
do
|
||||
echo "${keys[$key]}" = "${values[$key]}"
|
||||
done
|
||||
)
|
||||
)
|
||||
then
|
||||
results=$(
|
||||
Insert "$table" < <(
|
||||
for key in ${!keys[@]}
|
||||
do
|
||||
echo "${keys[$key]}" "${values[$key]}"
|
||||
done
|
||||
)
|
||||
)
|
||||
fi
|
||||
echo "$results"
|
||||
}
|
||||
67
lib/database/InsertOrUpdate
Normal file
67
lib/database/InsertOrUpdate
Normal file
@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
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" ${keys[0]} < <(
|
||||
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"
|
||||
}
|
||||
36
lib/database/Select
Normal file
36
lib/database/Select
Normal file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
Select() {
|
||||
#Select table [col1 [col2 [..]]] < WHERE_key WHERE_operator WHERE_value
|
||||
# [WHERE_key WHERE_operator WHERE_value
|
||||
# […]]
|
||||
local \
|
||||
table="$1" \
|
||||
col \
|
||||
columns \
|
||||
operator \
|
||||
results \
|
||||
where_statement
|
||||
shift
|
||||
for col
|
||||
do
|
||||
(( ${#columns} )) && columns+=','
|
||||
columns+="$col"
|
||||
done
|
||||
while read key operator value
|
||||
do
|
||||
(( ${#where_statement} )) && where_statement+=( "AND" )
|
||||
where_statement+=( "$key $operator "'"'"${value//\"/\"\"}"'"' )
|
||||
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
|
||||
}
|
||||
63
lib/database/Update
Normal file
63
lib/database/Update
Normal file
@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
Update() {
|
||||
#Update table set_key set_value [set_key set_value […]] < where_key where_operator where_value
|
||||
# [where_key where_operator where_value
|
||||
# […]]
|
||||
local \
|
||||
table="$1" \
|
||||
key \
|
||||
argument \
|
||||
operator \
|
||||
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)
|
||||
case $argument in
|
||||
'NULL')
|
||||
set_statement+=" = NULL"
|
||||
;;
|
||||
+([0-9])?(.+([0-9])))
|
||||
set_statement+=" = $argument"
|
||||
;;
|
||||
*)
|
||||
set_statement+=" = "'"'"${argument//\"/\"\"}"'"'
|
||||
;;
|
||||
esac
|
||||
what=key
|
||||
;;
|
||||
esac
|
||||
done
|
||||
while read key operator value
|
||||
do
|
||||
(( ${#where_statement} )) && where_statement+=( "AND" )
|
||||
case $value in
|
||||
'NULL')
|
||||
where_statement+=( "$key is NULL" )
|
||||
;;
|
||||
+([0-9.]))
|
||||
where_statement+=( "$key $operator $value" )
|
||||
;;
|
||||
*)
|
||||
where_statement+=( "$key $operator "'"'"${value//\"/\"\"}"'"' )
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo "UPDATE '$table' SET" \
|
||||
"$set_statement" \
|
||||
"WHERE" \
|
||||
"${where_statement[@]}" \
|
||||
";" >&3
|
||||
}
|
||||
10
lib/database/closeDatabase
Normal file
10
lib/database/closeDatabase
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
closeDatabase() {
|
||||
echo .quit >&3
|
||||
(( debug )) && echo -n "Waiting for SQLite to terminate... "
|
||||
wait
|
||||
(( debug )) && echo OK
|
||||
exec 3>&-
|
||||
exec 4<&-
|
||||
rm "$tempdir"/sqlite.{in,out}
|
||||
}
|
||||
28
lib/database/openDatabase
Normal file
28
lib/database/openDatabase
Normal file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
openDatabase() {
|
||||
if [ ! -d "$tempdir" ]
|
||||
then
|
||||
mkdir -p "$tempdir"
|
||||
fi
|
||||
rm -f "$tempdir"/sqlite.{in,out}
|
||||
mkfifo "$tempdir"/sqlite.{in,out}
|
||||
if [ ! -f "$database" ]
|
||||
then
|
||||
if [ ! -d "${database%/*}" ]
|
||||
then
|
||||
mkdir -p "${database%/*}"
|
||||
fi
|
||||
sqlite3 "$database" < $schema
|
||||
fi
|
||||
sqlite3 -bail "$database" \
|
||||
< "$tempdir/sqlite.in" \
|
||||
> "$tempdir/sqlite.out" &
|
||||
exec 3> "$tempdir"/sqlite.in
|
||||
exec 4< "$tempdir"/sqlite.out
|
||||
if (( debug > 2 ))
|
||||
then
|
||||
exec 5>&3
|
||||
exec 3> >(tee -a $tempdir/debug.log >&5)
|
||||
fi
|
||||
echo 'PRAGMA foreign_keys = ON;' >&3
|
||||
}
|
||||
49
lib/decode/decodeFile
Normal file
49
lib/decode/decodeFile
Normal file
@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
decodeFile() {
|
||||
if ! decodetaskid=$(
|
||||
Select tasks id <<<"key = $tmpfile"
|
||||
)
|
||||
then
|
||||
decodetaskid=$(
|
||||
Insert tasks <<-EOInsert
|
||||
key $tmpfile
|
||||
source_file $fileid
|
||||
$(
|
||||
for key in ${!commandline[@]}
|
||||
do
|
||||
echo "cmd_arg$key ${commandline[key]}"
|
||||
done
|
||||
)
|
||||
status 0
|
||||
EOInsert
|
||||
)
|
||||
progressSpin
|
||||
fi
|
||||
if (( sox_needed ))
|
||||
then
|
||||
cleanup="$tempdir/$tmpfile"
|
||||
decodeSox "$tempdir/$tmpfile.wav"
|
||||
if ! soxtaskid=$(
|
||||
Select tasks id <<<"key = $tmpfile"
|
||||
)
|
||||
then
|
||||
soxtaskid=$(
|
||||
Insert tasks <<-EOInsert
|
||||
key $tmpfile
|
||||
source_file $fileid
|
||||
$(
|
||||
for key in ${!commandline[@]}
|
||||
do
|
||||
echo "cmd_arg$key ${commandline[key]}"
|
||||
done
|
||||
)
|
||||
requires $decodetaskid
|
||||
required $decodetaskid
|
||||
status 0
|
||||
cleanup $cleanup
|
||||
EOInsert
|
||||
)
|
||||
progressSpin
|
||||
fi
|
||||
fi
|
||||
}
|
||||
6
lib/decode/decodeMpcdec
Normal file
6
lib/decode/decodeMpcdec
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
decodeMpcdec() {
|
||||
tmpfile="${fileid}mpcdec"
|
||||
commandline=(${ionice}mpcdec)
|
||||
commandline+=("$sourcepath/$filename" "$tempdir/$tmpfile.wav")
|
||||
}
|
||||
6
lib/decode/decodeOpusdec
Normal file
6
lib/decode/decodeOpusdec
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
decodeOpusdec() {
|
||||
tmpfile="${fileid}opusdec"
|
||||
commandline=(${ionice}opusdec)
|
||||
commandline+=("$sourcepath/$filename" "$tempdir/$tmpfile.wav")
|
||||
}
|
||||
31
lib/decode/decodeSox
Normal file
31
lib/decode/decodeSox
Normal file
@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
decodeSox() {
|
||||
commandline=(${ionice}sox --single-threaded --temp "$tempdir")
|
||||
soxoptions_in=''
|
||||
soxoptions_out=''
|
||||
if (( ${destinationnormalize["$destination"]} ))
|
||||
then
|
||||
commandline+=(--norm)
|
||||
soxoptions_in+=' --norm'
|
||||
fi
|
||||
if [ -n "$1" ]
|
||||
then
|
||||
commandline+=("$1")
|
||||
else
|
||||
commandline+=("$sourcepath/$filename")
|
||||
fi
|
||||
if [ -n "${destinationfrequency["$destination"]}" ] \
|
||||
&& (( ${rate:-0} != ${destinationfrequency["$destination"]} ))
|
||||
then
|
||||
commandline+=(-r ${destinationfrequency["$destination"]})
|
||||
soxoptions_out+=" -r ${destinationfrequency["$destination"]}"
|
||||
fi
|
||||
if [ -n "${destinationchannels["$destination"]}" ] \
|
||||
&& (( ${channels:-0} != ${destinationchannels["$destination"]} ))
|
||||
then
|
||||
commandline+=(-c ${destinationchannels["$destination"]})
|
||||
soxoptions_out+=" -c ${destinationchannels["$destination"]}"
|
||||
fi
|
||||
tmpfile="$fileid${soxoptions_in// /}${soxoptions_out// /}"
|
||||
commandline+=("$tempdir/$tmpfile.wav")
|
||||
}
|
||||
17
lib/destinations/createDestinations
Normal file
17
lib/destinations/createDestinations
Normal file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
createDestinations() {
|
||||
for destination in ${!destinationpath[@]}
|
||||
do
|
||||
if ! [ -d "${destinationpath["$destination"]}" ]
|
||||
then
|
||||
if ! mkdir -p "${destinationpath["$destination"]}"
|
||||
then
|
||||
echo "$destination: Could not create ${destinationpath["$destination"]}!"
|
||||
exit $EINVDEST
|
||||
fi
|
||||
fi
|
||||
destinationid["$destination"]=$(
|
||||
InsertIfUnset destinations <<<"name $destination"
|
||||
)
|
||||
done
|
||||
}
|
||||
32
lib/destinations/updateMimes
Normal file
32
lib/destinations/updateMimes
Normal file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
updateMimes() {
|
||||
Update mime_actions action 1 <<<"action != 1"
|
||||
for destination in ${!destinationskipmime[@]}
|
||||
do
|
||||
IFS='|'
|
||||
for mime_type in ${destinationskipmime["$destination"]}
|
||||
do
|
||||
IFS="$oldIFS"
|
||||
Update mime_type_actions action 0 >/dev/null < <(
|
||||
cat <<-EOWhere
|
||||
destination_id = ${destinationid["$destination"]}
|
||||
mime_text LIKE ${mime_type//\*/%}
|
||||
EOWhere
|
||||
)
|
||||
done
|
||||
done
|
||||
for destination in ${!destinationcopymime[@]}
|
||||
do
|
||||
IFS='|'
|
||||
for mime_type in ${destinationcopymime["$destination"]}
|
||||
do
|
||||
IFS="$oldIFS"
|
||||
Update mime_type_actions action 2 >/dev/null < <(
|
||||
cat <<-EOWhere
|
||||
destination_id = ${destinationid["$destination"]}
|
||||
mime_text LIKE ${mime_type//\*/%}
|
||||
EOWhere
|
||||
)
|
||||
done
|
||||
done
|
||||
}
|
||||
64
lib/encode/encodeFile::mp3
Normal file
64
lib/encode/encodeFile::mp3
Normal file
@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
encodeFile::mp3() {
|
||||
lameopts=(${ionice}lame --quiet)
|
||||
lameopts+=(-v --abr ${destinationquality[$destination]})
|
||||
[ -n "$album" ] && lameopts+=(--tl "$album" )
|
||||
[ -n "$artist" ] && lameopts+=(--ta "$artist")
|
||||
[ -n "$genre" ] && lameopts+=(--tg "$genre")
|
||||
[ -n "$title" ] && lameopts+=(--tt "$title")
|
||||
[ -n "$track" ] && lameopts+=(--tn "$track")
|
||||
[ -n "$year" ] && lameopts+=(--ty "$year")
|
||||
if (( ${destinationnoresample[$destination]:-0} == 1 ))
|
||||
then
|
||||
# If 'rate' is not one of these value, it cannot be encoded to
|
||||
# MP3, in which case we'd be better of letting lame decide which
|
||||
# rate to use.
|
||||
if [ -n "${destinationfrequency["$destination"]}" ]
|
||||
then
|
||||
case ${destinationfrequency["$destination"]} in
|
||||
48000) lameopts+=(--resample 48) ;;
|
||||
44100) lameopts+=(--resample 44.1) ;;
|
||||
32000) lameopts+=(--resample 32) ;;
|
||||
24000) lameopts+=(--resample 24) ;;
|
||||
22050) lameopts+=(--resample 22.05) ;;
|
||||
16000) lameopts+=(--resample 16) ;;
|
||||
12000) lameopts+=(--resample 12) ;;
|
||||
11025) lameopts+=(--resample 11.025) ;;
|
||||
8000) lameopts+=(--resample 8) ;;
|
||||
esac
|
||||
else
|
||||
case $rate in
|
||||
48000) lameopts+=(--resample 48) ;;
|
||||
44100) lameopts+=(--resample 44.1) ;;
|
||||
32000) lameopts+=(--resample 32) ;;
|
||||
24000) lameopts+=(--resample 24) ;;
|
||||
22050) lameopts+=(--resample 22.05) ;;
|
||||
16000) lameopts+=(--resample 16) ;;
|
||||
12000) lameopts+=(--resample 12) ;;
|
||||
11025) lameopts+=(--resample 11.025) ;;
|
||||
8000) lameopts+=(--resample 8) ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
lameopts+=("$tempdir/$tmpfile.wav" "$destdir/$destfile.mp3")
|
||||
encodetaskid=$(
|
||||
Insert tasks <<-EOInsert
|
||||
key ${fileid}lame$destination
|
||||
requires ${soxtaskid:-$decodetaskid}
|
||||
required ${soxtaskid:-$decodetaskid}
|
||||
fileid $destfileid
|
||||
filename $destdir/$destfile.mp3
|
||||
$(
|
||||
for key in ${!lameopts[@]}
|
||||
do
|
||||
echo "cmd_arg$key ${lameopts[key]}"
|
||||
done
|
||||
)
|
||||
cleanup $tempdir/$tmpfile.wav
|
||||
source_file $fileid
|
||||
status 0
|
||||
rename_pattern ${destinationrenamepath[$destination]}/${destinationrename[$destination]}:${destinationfat32compat["$destination"]}
|
||||
EOInsert
|
||||
)
|
||||
progressSpin
|
||||
}
|
||||
39
lib/encode/encodeFile::opus
Normal file
39
lib/encode/encodeFile::opus
Normal file
@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
encodeFile::opus() {
|
||||
opusencopts=(${ionice}opusenc --music --quiet)
|
||||
opusencopts+=(--bitrate ${destinationquality[$destination]})
|
||||
[ -n "${destinationloss["$destination"]}" ] \
|
||||
&& opusencopts+=(--expect-loss "${destinationloss["$destination"]}")
|
||||
[ -n "$albumartist" ] && opusencopts+=(--comment "ALBUMARTIST=$albumartist")
|
||||
[ -n "$album" ] && opusencopts+=(--comment "ALBUM=$album")
|
||||
[ -n "$artist" ] && opusencopts+=(--artist "$artist")
|
||||
[ -n "$composer" ] && opusencopts+=(--comment "COMPOSER=$composer")
|
||||
[ -n "$disc" ] && opusencopts+=(--comment "DISCNUMBER=$disc")
|
||||
[ -n "$genre" ] && opusencopts+=(--comment "GENRE=$genre")
|
||||
[ -n "$performer" ] && opusencopts+=(--comment "PERFORMER=$performer")
|
||||
[ -n "$title" ] && opusencopts+=(--title "$title")
|
||||
[ -n "$track" ] && opusencopts+=(--comment "TRACKNUMBER=${track%/*}")
|
||||
[ -n "${track#*/}" ] && opusencopts+=(--comment "TRACKTOTAL=${track#*/}")
|
||||
[ -n "$year" ] && opusencopts+=(--comment "DATE=$year")
|
||||
opusencopts+=("$tempdir/$tmpfile.wav" "$destdir/$destfile.opus")
|
||||
encodetaskid=$(
|
||||
Insert tasks <<-EOInsert
|
||||
key ${fileid}opusenc$destination
|
||||
requires ${soxtaskid:-$decodetaskid}
|
||||
required ${soxtaskid:-$decodetaskid}
|
||||
fileid $destfileid
|
||||
filename $destdir/$destfile.ogg
|
||||
$(
|
||||
for key in ${!opusencopts[@]}
|
||||
do
|
||||
echo "cmd_arg$key ${opusencopts[key]}"
|
||||
done
|
||||
)
|
||||
cleanup $tempdir/$tmpfile.wav
|
||||
source_file $fileid
|
||||
status 0
|
||||
rename_pattern ${destinationrenamepath[$destination]}/${destinationrename[$destination]}:${destinationfat32compat["$destination"]}
|
||||
EOInsert
|
||||
)
|
||||
progressSpin
|
||||
}
|
||||
35
lib/encode/encodeFile::vorbis
Normal file
35
lib/encode/encodeFile::vorbis
Normal file
@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
encodeFile::vorbis() {
|
||||
oggencopts=(${ionice}oggenc -Q -q ${destinationquality[$destination]})
|
||||
[ -n "$albumartist" ] && oggencopts+=(-c "ALBUMARTIST=$albumartist")
|
||||
[ -n "$album" ] && oggencopts+=(-l "$album")
|
||||
[ -n "$artist" ] && oggencopts+=(-a "$artist")
|
||||
[ -n "$composer" ] && oggencopts+=(-c "COMPOSER=$composer")
|
||||
[ -n "$disc" ] && oggencopts+=(-c "DISCNUMBER=$disc")
|
||||
[ -n "$genre" ] && oggencopts+=(-G "$genre")
|
||||
[ -n "$performer" ] && oggencopts+=(-c "PERFORMER=$performer")
|
||||
[ -n "$title" ] && oggencopts+=(-t "$title")
|
||||
[ -n "$track" ] && oggencopts+=(-N "$track")
|
||||
[ -n "$year" ] && oggencopts+=(-d "$year")
|
||||
oggencopts+=(-o "$destdir/$destfile.ogg" "$tempdir/$tmpfile.wav")
|
||||
encodetaskid=$(
|
||||
Insert tasks <<-EOInsert
|
||||
key ${fileid}oggenc$destination
|
||||
requires ${soxtaskid:-$decodetaskid}
|
||||
required ${soxtaskid:-$decodetaskid}
|
||||
fileid $destfileid
|
||||
filename $destdir/$destfile.ogg
|
||||
$(
|
||||
for key in ${!oggencopts[@]}
|
||||
do
|
||||
echo "cmd_arg$key ${oggencopts[key]}"
|
||||
done
|
||||
)
|
||||
cleanup $tempdir/$tmpfile.wav
|
||||
source_file $fileid
|
||||
status 0
|
||||
rename_pattern ${destinationrenamepath[$destination]}/${destinationrename[$destination]}:${destinationfat32compat["$destination"]}
|
||||
EOInsert
|
||||
)
|
||||
progressSpin
|
||||
}
|
||||
35
lib/files/getDestDir
Normal file
35
lib/files/getDestDir
Normal file
@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
getDestDir() {
|
||||
destdir="${destinationpath[$destination]}/"
|
||||
if [ -n "${destinationrenamepath[$destination]}" ]
|
||||
then
|
||||
destdir+="${destinationrenamepath[$destination]//%\{album\}/$album}"
|
||||
replace=$(sanitizeFile "$albumartist")
|
||||
destdir="${destdir//%\{albumartist\}/$replace}"
|
||||
replace=$(sanitizeFile "$artist")
|
||||
destdir="${destdir//%\{artist\}/$replace}"
|
||||
replace=$(sanitizeFile "$genre")
|
||||
destdir="${destdir//%\{genre\}/$replace}"
|
||||
replace=$(sanitizeFile "$title")
|
||||
destdir="${destdir//%\{title\}/$replace}"
|
||||
tracknumber="${track%/*}"
|
||||
replace=$(sanitizeFile "$tracknumber")
|
||||
destdir="${destdir//%\{track\}/$replace}"
|
||||
replace=$(sanitizeFile "$year")
|
||||
destdir="${destdir//%\{year\}/$replace}"
|
||||
replace=$(sanitizeFile "$disc")
|
||||
destdir="${destdir//%\{disc\}/$replace}"
|
||||
else
|
||||
destdir+=$(sanitizeFile "${filename%%/*}")
|
||||
part=${filename#*/}
|
||||
while [[ $part =~ / ]]
|
||||
do
|
||||
destdir+="/$(sanitizeFile "${part%%/*}")"
|
||||
part=${part#*/}
|
||||
done
|
||||
fi
|
||||
if ! [ -d "$destdir" ]
|
||||
then
|
||||
mkdir -p "$destdir"
|
||||
fi
|
||||
}
|
||||
19
lib/files/getDestFile
Normal file
19
lib/files/getDestFile
Normal file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
getDestFile() {
|
||||
if [ -n "${destinationrename[$destination]}" ]
|
||||
then
|
||||
destfile="${destinationrename[$destination]//%\{album\}/$album}"
|
||||
destfile="${destfile//%\{albumartist\}/$albumartist}"
|
||||
destfile="${destfile//%\{artist\}/$artist}"
|
||||
destfile="${destfile//%\{genre\}/$genre}"
|
||||
destfile="${destfile//%\{title\}/$title}"
|
||||
tracknumber="${track%/*}"
|
||||
destfile="${destfile//%\{track\}/$tracknumber}"
|
||||
destfile="${destfile//%\{year\}/$year}"
|
||||
destfile="${destfile//%\{disc\}/$disc}"
|
||||
else
|
||||
destfile="${filename##*/}"
|
||||
destfile="${destfile%.*}"
|
||||
fi
|
||||
destfile=$(sanitizeFile "$destfile")
|
||||
}
|
||||
64
lib/files/getFiles
Normal file
64
lib/files/getFiles
Normal file
@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
getFiles() {
|
||||
scantime=$(date +%s)
|
||||
for prune_expression in "${skippeddirectories[@]}"
|
||||
do
|
||||
prunes+="-path $sourcepath$prune_expression -prune -o "
|
||||
done
|
||||
echo -n "Scanning $sourcepath... "
|
||||
# We probably have thousands of files, don't waste time on disk writes
|
||||
echo 'BEGIN TRANSACTION;' >&3
|
||||
while read time size filename
|
||||
do
|
||||
if ! Select source_files id >/dev/null <<-EOWhere
|
||||
filename = $filename
|
||||
mime_type > 0
|
||||
last_change = $time
|
||||
EOWhere
|
||||
then
|
||||
mimetype=$(file -b --mime-type "$sourcepath/$filename")
|
||||
if [[ $mimetype == application/ogg ]]
|
||||
then
|
||||
case "$(head -n1 "$sourcepath/$filename")" in
|
||||
*'vorbis'*)
|
||||
mimetype+=' vorbis'
|
||||
;;
|
||||
*'OpusHead'*)
|
||||
mimetype+=' opus'
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
mimetypeid=$(
|
||||
InsertIfUnset mime_types <<-EOInsert
|
||||
mime_text $mimetype
|
||||
EOInsert
|
||||
)
|
||||
InsertOrUpdate source_files \
|
||||
last_change $time \
|
||||
size $size \
|
||||
last_seen $scantime \
|
||||
mime_type $mimetypeid \
|
||||
>/dev/null \
|
||||
<<-EOWhere
|
||||
filename $filename
|
||||
EOWhere
|
||||
(( ++new ))
|
||||
if (( new % 1000 == 0 ))
|
||||
then
|
||||
echo 'COMMIT;BEGIN TRANSACTION;' >&3
|
||||
(( debug )) \
|
||||
&& echo -ne "\bCommitted $count files... "
|
||||
fi
|
||||
else
|
||||
Update source_files last_seen $scantime <<-EOWhere
|
||||
filename = $filename
|
||||
EOWhere
|
||||
fi
|
||||
progressSpin
|
||||
done < <(
|
||||
find "$sourcepath" $prunes -type f -printf "%T@ %s %P\n"
|
||||
)
|
||||
echo 'COMMIT;' >&3
|
||||
echo -e "\r${count:-0} files found, ${new:=0} new or changed."
|
||||
unset count
|
||||
}
|
||||
6
lib/files/removeObsoleteFiles
Normal file
6
lib/files/removeObsoleteFiles
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
removeObsoleteFiles() {
|
||||
Delete source_files <<-EOWhere
|
||||
last_seen < $scantime
|
||||
EOWhere
|
||||
}
|
||||
24
lib/files/sanitizeFile
Normal file
24
lib/files/sanitizeFile
Normal file
@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
sanitizeFile() {
|
||||
shopt -s extglob
|
||||
string="$1"
|
||||
# Filenames can't contain /
|
||||
string="${string//\// }"
|
||||
if (( ${destinationfat32compat[$destination]} ))
|
||||
then
|
||||
# Filenames can't contain:
|
||||
string=${string//\?/ }
|
||||
string=${string//\\/ }
|
||||
string=${string//</ }
|
||||
string=${string//>/ }
|
||||
string=${string//:/ }
|
||||
string=${string//\*/ }
|
||||
string=${string//|/ }
|
||||
string=${string//\"/ }
|
||||
|
||||
# Filenames can't begin or end with ' '
|
||||
string=${string/#+( )/}
|
||||
string=${string/%+( )/}
|
||||
fi
|
||||
echo "$string"
|
||||
}
|
||||
55
lib/tags/getInfos::APE
Normal file
55
lib/tags/getInfos::APE
Normal file
@ -0,0 +1,55 @@
|
||||
#!/bin/bash
|
||||
getInfosAPE_version='APE-1'
|
||||
tagreaders+=( "$getInfosAPE_version" )
|
||||
getInfos::APE() {
|
||||
# I was not able to find a decent cli tool to read APE tags.
|
||||
# This is raw but works for the very few MusePack files I got.
|
||||
#
|
||||
# Please tell me if you know of any good tool.
|
||||
tagreader="$getInfosAPE_version"
|
||||
IFS='='
|
||||
while read tag value
|
||||
do
|
||||
IFS="$oldIFS"
|
||||
case $tag in
|
||||
[Aa][Ll][Bb][Uu][Mm]' '[Aa][Rr][Tt][Ii][Ss][Tt])
|
||||
albumartist="$value"
|
||||
;;
|
||||
[Aa][Rr][Tt][Ii][Ss][Tt])
|
||||
artist="$value"
|
||||
;;
|
||||
[Yy][Ee][Aa][Rr])
|
||||
year="$value"
|
||||
;;
|
||||
[Aa][Ll][Bb][Uu][Mm])
|
||||
album="$value"
|
||||
;;
|
||||
[Tt][Ii][Tt][Ll][Ee])
|
||||
title="$value"
|
||||
;;
|
||||
[Tt][Rr][Aa][Cc][Kk])
|
||||
tracknum="$value"
|
||||
;;
|
||||
[Gg][Ee][Nn][Rr][Ee])
|
||||
genre="$value"
|
||||
;;
|
||||
[Cc][Oo][Mm][Pp][Oo][Ss][Ee][Rr])
|
||||
composer="$value"
|
||||
;;
|
||||
[Pp][Ee][Rr][Ff][Oo][Rr][Mm][Ee][Rr])
|
||||
performer="$value"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
IFS='='
|
||||
done < <(
|
||||
IFS="$oldIFS"
|
||||
sed \
|
||||
's/APETAGEX/\n/;s/[\x00\-\x1F]\x00\+/\n/g;s/\x00/=/g' \
|
||||
"$sourcepath/$filename" \
|
||||
| egrep -i \
|
||||
'^(Album Artist|Artist|Year|Album|Title|Track|Genre|Composer|Performer)='
|
||||
)
|
||||
IFS="$oldIFS"
|
||||
}
|
||||
45
lib/tags/getInfos::FLAC
Normal file
45
lib/tags/getInfos::FLAC
Normal file
@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
getInfosFLAC_version='FLAC-1'
|
||||
tagreaders+=( "$getInfosFLAC_version" )
|
||||
getInfos::FLAC() {
|
||||
tagreader="$getInfosFLAC_version"
|
||||
infos=$(
|
||||
metaflac \
|
||||
--show-tag=ALBUM \
|
||||
--show-tag=ALBUMARTIST \
|
||||
--show-tag=ARTIST \
|
||||
--show-tag=COMPOSER \
|
||||
--show-tag=DATE \
|
||||
--show-tag=DISCNUMBER \
|
||||
--show-tag=GENRE \
|
||||
--show-tag=PERFORMER \
|
||||
--show-tag=TITLE \
|
||||
--show-tag=TRACKNUMBER \
|
||||
--show-tag=TRACKTOTAL \
|
||||
"$sourcepath/$filename"
|
||||
)
|
||||
albumartist=$(gettag albumartist)
|
||||
album=$(gettag album)
|
||||
artist=$(gettag artist)
|
||||
composer=$(gettag composer)
|
||||
disc=$(gettag discnumber)
|
||||
genre=$(gettag genre)
|
||||
performer=$(gettag performer)
|
||||
title=$(gettag title)
|
||||
tracknum="$(gettag tracknumber)/$(gettag tracktotal)"
|
||||
year=$(gettag date)
|
||||
if [ -n "$tracknum" -a -n "$tracktotal" ]
|
||||
then
|
||||
tracknum="$tracknum/$tracktotal"
|
||||
fi
|
||||
year=$(gettag DATE)
|
||||
{
|
||||
read rate
|
||||
read channels
|
||||
} < <(
|
||||
metaflac \
|
||||
--show-sample-rate \
|
||||
--show-channels \
|
||||
"$sourcepath/$filename"
|
||||
)
|
||||
}
|
||||
29
lib/tags/getInfos::MP3
Normal file
29
lib/tags/getInfos::MP3
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
getInfosMP3_version='ID3-2'
|
||||
tagreaders+=( "$getInfosMP3_version" )
|
||||
getInfos::MP3() {
|
||||
tagreader="$getInfosMP3_version"
|
||||
infos=$(
|
||||
soxi "$sourcepath/$filename" 2>/dev/null \
|
||||
| sed 's/ *: /=/'
|
||||
)
|
||||
album=$(gettag album)
|
||||
artist=$(gettag artist)
|
||||
genre=$(gettag genre)
|
||||
title=$(gettag title)
|
||||
tracknum=$(gettag tracknumber)
|
||||
year=$(gettag year)
|
||||
expr='^\([0-9]*\)$'
|
||||
if [[ $genre =~ $expr ]]
|
||||
then
|
||||
genre=${genre%)}
|
||||
genre=${genre#(}
|
||||
genre="${id3genres[$genre]}"
|
||||
fi
|
||||
infos="${infos/: /=}"
|
||||
channels=$(gettag channels)
|
||||
rate=$(gettag 'sample rate')
|
||||
bitrate=$(gettag 'bit rate')
|
||||
bitrate=${bitrate%%.*}
|
||||
bitrate=${bitrate%k}
|
||||
}
|
||||
30
lib/tags/getInfos::Ogg
Normal file
30
lib/tags/getInfos::Ogg
Normal file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
getInfosOgg_version='Ogg-1'
|
||||
tagreaders+=( "$getInfosOgg_version" )
|
||||
getInfos::Ogg() {
|
||||
tagreader="$getInfosOgg_version"
|
||||
infos=$(
|
||||
ogginfo "$sourcepath/$filename" \
|
||||
| sed 's/\t//'
|
||||
)
|
||||
albumartist=$(gettag albumartist)
|
||||
album=$(gettag album)
|
||||
artist=$(gettag artist)
|
||||
composer=$(gettag composer)
|
||||
disc=$(gettag discnumber)
|
||||
genre=$(gettag genre)
|
||||
performer=$(gettag performer)
|
||||
title=$(gettag title)
|
||||
tracknum=$(gettag tracknumber)
|
||||
tracktotal=$(gettag tracktotal)
|
||||
if [ -n "$tracknum" -a -n "$tracktotal" ]
|
||||
then
|
||||
tracknum="$tracknum/$tracktotal"
|
||||
fi
|
||||
year=$(gettag date)
|
||||
infos="${infos/: /=}"
|
||||
rate=$(gettag rate|head -n1)
|
||||
channels=$(gettag channels|head -n1)
|
||||
bitrate=$(gettag 'nominal bitrate')
|
||||
bitrate=${bitrate%%,*}
|
||||
}
|
||||
30
lib/tags/getInfos::Opus
Normal file
30
lib/tags/getInfos::Opus
Normal file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
getInfosOpus_version='Opus-1'
|
||||
tagreaders+=( "$getInfosOpus_version" )
|
||||
getInfos::Opus() {
|
||||
tagreader="$getInfosOpus_version"
|
||||
infos=$(
|
||||
opusinfo "$sourcepath/$filename" \
|
||||
| sed 's/\t//'
|
||||
)
|
||||
albumartist=$(gettag albumartist)
|
||||
album=$(gettag album)
|
||||
artist=$(gettag artist)
|
||||
composer=$(gettag composer)
|
||||
disc=$(gettag discnumber)
|
||||
genre=$(gettag genre)
|
||||
performer=$(gettag performer)
|
||||
title=$(gettag title)
|
||||
tracknum=$(gettag tracknumber)
|
||||
tracktotal=$(gettag tracktotal)
|
||||
if [ -n "$tracknum" -a -n "$tracktotal" ]
|
||||
then
|
||||
tracknum="$tracknum/$tracktotal"
|
||||
fi
|
||||
year=$(gettag date)
|
||||
infos="${infos/: /=}"
|
||||
rate=$(gettag 'original sample rate'|head -n1)
|
||||
channels=$(gettag channels|head -n1)
|
||||
bitrate=$(gettag 'average bitrate')
|
||||
bitrate=${bitrate%%.*}
|
||||
}
|
||||
16
lib/tags/getRateChannelMPC
Normal file
16
lib/tags/getRateChannelMPC
Normal file
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
getRateChannelMPC() {
|
||||
while read key value garbage
|
||||
do
|
||||
case $key in
|
||||
'samplerate:')
|
||||
rate=$value
|
||||
;;
|
||||
'channels:')
|
||||
channels=$value
|
||||
;;
|
||||
esac
|
||||
done < <(
|
||||
mpcdec "$sourcepath/$filename" -i 2>&1
|
||||
)
|
||||
}
|
||||
5
lib/tags/getRateChannelSoxi
Normal file
5
lib/tags/getRateChannelSoxi
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
getRateChannelSoxi() {
|
||||
rate=$(soxi -r "$sourcepath/$filename" 2>/dev/null)
|
||||
channels=$(soxi -c "$sourcepath/$filename" 2>/dev/null)
|
||||
}
|
||||
42
lib/tags/getTags
Normal file
42
lib/tags/getTags
Normal file
@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
getTags_version='unknown-2'
|
||||
tagreaders+=( "$getTags_version" )
|
||||
getTags() {
|
||||
unset type
|
||||
case "$mimetype" in
|
||||
audio/mpeg)
|
||||
type=MP3
|
||||
;;
|
||||
'application/ogg opus')
|
||||
type=Opus
|
||||
;;
|
||||
application/ogg*)
|
||||
type=Ogg
|
||||
;;
|
||||
audio/x-flac)
|
||||
type=FLAC
|
||||
;;
|
||||
*)
|
||||
extendedtype=$(file -b "$sourcepath/$filename")
|
||||
case "$extendedtype" in
|
||||
*' ID3 '*)
|
||||
type=MP3
|
||||
;;
|
||||
*'Musepack '*)
|
||||
getRateChannelMPC
|
||||
tryAPE
|
||||
;;
|
||||
*)
|
||||
getRateChannelSoxi
|
||||
tryAPE
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
if [ -n "$type" ]
|
||||
then
|
||||
getInfos::$type
|
||||
else
|
||||
tagreader=$getTags_version
|
||||
fi
|
||||
}
|
||||
5
lib/tags/gettag
Normal file
5
lib/tags/gettag
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
gettag() {
|
||||
echo -e "$infos" \
|
||||
| sed -n "/^${1}=/I{s/^${1}=//I;p;q}"
|
||||
}
|
||||
6
lib/tags/tryAPE
Normal file
6
lib/tags/tryAPE
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
tryAPE() {
|
||||
grep -q 'APETAGEX' \
|
||||
"$sourcepath/$filename" \
|
||||
&& type=APE
|
||||
}
|
||||
27
lib/tasks/gettaskinfos
Normal file
27
lib/tasks/gettaskinfos
Normal file
@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
gettaskinfos() {
|
||||
echo '
|
||||
SELECT
|
||||
id,
|
||||
source_file,
|
||||
required,
|
||||
cleanup,
|
||||
fileid,
|
||||
filename
|
||||
FROM tasks
|
||||
WHERE id='$1';
|
||||
' >&3
|
||||
read -u4 line
|
||||
taskid=${line%%|*}
|
||||
rest="${line#*|}|"
|
||||
sourcefileid=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
required=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
cleanup=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
destfileid=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
destfilename=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
}
|
||||
10
lib/tools/progressSpin
Normal file
10
lib/tools/progressSpin
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
progressSpin() {
|
||||
case $(( ++count % 40 )) in
|
||||
0) echo -ne '\b|' ;;
|
||||
10) echo -ne '\b/' ;;
|
||||
20) echo -en '\b-' ;;
|
||||
30) echo -ne '\b\\' ;;
|
||||
*) ;;
|
||||
esac
|
||||
}
|
||||
20
lib/workers/checkworkers
Normal file
20
lib/workers/checkworkers
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
checkworkers() {
|
||||
for key in ${!workers[@]}
|
||||
do
|
||||
if ! kill -0 ${workers[key]} 2>/dev/null
|
||||
then
|
||||
taskid=${workertasks[key]}
|
||||
(( ++ran ))
|
||||
(( active-- ))
|
||||
if destroyworker $key
|
||||
then
|
||||
finishedtasks+=($taskid)
|
||||
else
|
||||
failedtasks+=($taskid)
|
||||
(( ++failed ))
|
||||
fi
|
||||
unset workertasks[key]
|
||||
fi
|
||||
done
|
||||
}
|
||||
65
lib/workers/cleaner
Normal file
65
lib/workers/cleaner
Normal file
@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
cleaner() {
|
||||
for key in ${!failedtasks[@]}
|
||||
do
|
||||
taskid=${failedtasks[key]}
|
||||
gettaskinfos $taskid
|
||||
faildepends=$(
|
||||
Select tasks 'COUNT(*)' <<-EOWhere
|
||||
requires = $taskid
|
||||
EOWhere
|
||||
)
|
||||
(( failed+=faildepends ))
|
||||
Update tasks status 2 <<<"id = $taskid"
|
||||
Update tasks status 2 <<<"requires = $taskid"
|
||||
echo "SELECT COUNT(*)
|
||||
FROM tasks
|
||||
WHERE ( status = 0 OR status = 1 )
|
||||
AND required = $taskid;">&3
|
||||
read -u4 count
|
||||
if (( count == 0 ))
|
||||
then
|
||||
rm -f "$cleanup"
|
||||
fi
|
||||
unset failedtasks[key]
|
||||
done
|
||||
for key in ${!finishedtasks[@]}
|
||||
do
|
||||
taskid=${finishedtasks[key]}
|
||||
gettaskinfos $taskid
|
||||
if [ -n "$destfilename" ]
|
||||
then
|
||||
echo \
|
||||
"UPDATE destination_files" \
|
||||
"SET filename=\"${destfilename//\"/\"\"}\"," \
|
||||
" last_change=(" \
|
||||
" SELECT last_change" \
|
||||
" FROM source_files" \
|
||||
" WHERE id=$sourcefileid" \
|
||||
" )," \
|
||||
" old_filename=(" \
|
||||
" SELECT filename" \
|
||||
" FROM destination_files" \
|
||||
" WHERE id=$destfileid" \
|
||||
" )," \
|
||||
" rename_pattern=(" \
|
||||
" SELECT rename_pattern" \
|
||||
" FROM tasks" \
|
||||
" WHERE id=$taskid" \
|
||||
" )" \
|
||||
"WHERE id=$destfileid;" \
|
||||
>&3
|
||||
fi
|
||||
echo "SELECT COUNT(*)
|
||||
FROM tasks
|
||||
WHERE ( status = 0 OR status = 1 )
|
||||
AND required = $taskid;">&3
|
||||
read -u4 count
|
||||
if (( count == 0 ))
|
||||
then
|
||||
rm -f "$cleanup"
|
||||
fi
|
||||
Delete tasks <<<"id = $taskid"
|
||||
unset finishedtasks[key]
|
||||
done
|
||||
}
|
||||
5
lib/workers/createworker
Normal file
5
lib/workers/createworker
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
createworker() {
|
||||
worker $1 &
|
||||
workers[$1]=$!
|
||||
}
|
||||
6
lib/workers/destroyworker
Normal file
6
lib/workers/destroyworker
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
destroyworker() {
|
||||
dyingworker=${workers[$1]}
|
||||
unset workers[$1]
|
||||
wait $dyingworker
|
||||
}
|
||||
15
lib/workers/getworkerid
Normal file
15
lib/workers/getworkerid
Normal file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
getworkerid() {
|
||||
local i
|
||||
for (( i=0 ; i >= 0 ; i++ ))
|
||||
do
|
||||
if [ -z "${workers[i]}" ]
|
||||
then
|
||||
echo $i
|
||||
return
|
||||
fi
|
||||
done
|
||||
# If we reach this, we have reached the signed long limit
|
||||
# (2^63 - 1 = 9223372036854775807 - Got a supercomputer?)
|
||||
(( concurrency-- ))
|
||||
}
|
||||
154
lib/workers/master
Normal file
154
lib/workers/master
Normal file
@ -0,0 +1,154 @@
|
||||
#!/bin/bash
|
||||
master() {
|
||||
if (( active >= concurrency)) || [ -n "$quit" ]
|
||||
then
|
||||
sleep 0.1
|
||||
else
|
||||
echo '
|
||||
SELECT COUNT(*)
|
||||
FROM tasks
|
||||
WHERE status = 0;
|
||||
|
||||
SELECT COUNT(*)
|
||||
FROM tasks
|
||||
WHERE status = 0
|
||||
AND requires is NULL;
|
||||
|
||||
SELECT
|
||||
id,
|
||||
source_file,
|
||||
required,
|
||||
cmd_arg0,
|
||||
cmd_arg1,
|
||||
cmd_arg2,
|
||||
cmd_arg3,
|
||||
cmd_arg4,
|
||||
cmd_arg5,
|
||||
cmd_arg6,
|
||||
cmd_arg7,
|
||||
cmd_arg8,
|
||||
cmd_arg9,
|
||||
cmd_arg10,
|
||||
cmd_arg11,
|
||||
cmd_arg12,
|
||||
cmd_arg13,
|
||||
cmd_arg14,
|
||||
cmd_arg15,
|
||||
cmd_arg16,
|
||||
cmd_arg17,
|
||||
cmd_arg18,
|
||||
cmd_arg19,
|
||||
cmd_arg20,
|
||||
cmd_arg21,
|
||||
cmd_arg22,
|
||||
cmd_arg23,
|
||||
cmd_arg24,
|
||||
cmd_arg25,
|
||||
cmd_arg26,
|
||||
cmd_arg27,
|
||||
cmd_arg28,
|
||||
cmd_arg29,
|
||||
cleanup,
|
||||
fileid,
|
||||
filename
|
||||
FROM tasks
|
||||
WHERE status = 0
|
||||
AND requires is NULL
|
||||
ORDER BY source_file
|
||||
LIMIT 1;
|
||||
' >&3
|
||||
read -u4 remaining
|
||||
read -u4 ready
|
||||
if (( remaining == 0 ))
|
||||
then
|
||||
sleep 0.1
|
||||
continue
|
||||
elif (( ready == 0 ))
|
||||
then
|
||||
sleep 0.1
|
||||
else
|
||||
(( ++active ))
|
||||
read -u4 line
|
||||
taskid=${line%%|*}
|
||||
rest="${line#*|}|"
|
||||
sourcefileid=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
required=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
cmd_arg=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cmd_arg+=("${rest%%|*}")
|
||||
rest=${rest#*|}
|
||||
cleanup=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
destfileid=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
destfilename=${rest%%|*}
|
||||
rest=${rest#*|}
|
||||
for key in ${!cmd_arg[@]}
|
||||
do
|
||||
[ -z "${cmd_arg[key]}" ] && unset cmd_arg[key]
|
||||
done
|
||||
workerid=$(getworkerid)
|
||||
workertasks[workerid]=$taskid
|
||||
Update tasks status 1 <<<"id = $taskid"
|
||||
createworker $workerid
|
||||
fi
|
||||
fi
|
||||
}
|
||||
15
lib/workers/worker
Normal file
15
lib/workers/worker
Normal file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
worker() {
|
||||
exec 2>>"$tempdir/worker$1.log"
|
||||
(( debug >= 2 )) && echo "${cmd_arg[@]}" >&2
|
||||
"${cmd_arg[@]}" >/dev/null
|
||||
}
|
||||
createworker() {
|
||||
worker $1 &
|
||||
workers[$1]=$!
|
||||
}
|
||||
destroyworker() {
|
||||
dyingworker=${workers[$1]}
|
||||
unset workers[$1]
|
||||
wait $dyingworker
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user