Comment config handling (#LLM-assisted - Claude Code)

This commit is contained in:
Vincent Riquer 2026-03-13 02:26:32 +01:00
parent d680d52425
commit c99825912f
7 changed files with 192 additions and 30 deletions

7
configure vendored
View File

@ -1,25 +1,28 @@
#!/usr/bin/env bash
# defaults
# Default install prefix if --prefix= is not provided
default_prefix=/usr/local
#default_bindir=$default_prefix/bin
#default_libdir=$default_prefix/lib
#default_sharedir=$default_prefix/share
# Parse command-line arguments (only --prefix=VALUE is supported)
while (( $# ))
do
case "$1" in
--prefix=*) prefix="${1#*=}"
--prefix=*) prefix="${1#*=}" # Strip the "--prefix=" portion to get the value
;;
esac
shift
done
# Derive install directories from prefix (or default_prefix if unset)
bindir="${prefix:-$default_prefix}"/bin
libdir="${prefix:-$default_prefix}"/lib/AtOM
sharedir="${prefix:-$default_prefix}"/share/AtOM
docdir="${prefix:-$default_prefix}"/share/doc/AtOM
# Write Makefile.in so the Makefile can substitute real paths at build time
cat > Makefile.in <<-EOMakefile.in
bindir = "$bindir"
libdir = "$libdir"

View File

@ -1,27 +1,47 @@
#!/bin/bash
# Copyright © 2012-2026 ScriptFanix
# This program 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.
# This program 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.
# A copy of the GNU General Public License v3 is includded in the LICENSE file
# at the root of the project.
getConfig() {
# Read the config file line by line; 'key' gets the first word, 'value'
# the rest
while read key value
do
case $key in
'#'*)
#comment
#comment - skip comment lines
;;
'')
#empty line
#empty line - skip blank lines
;;
'[general]')
# Switch parsing context to the [general] section
context=General
;;
'[source]')
# Switch parsing context to the [source] section
context=Source
;;
\[*\])
# Any other [section] header is a destination name
context=Destination
destination="${key#[}"
destination="${destination%]}"
destinations+=("${destination%]}")
destinations+=("${destination%]}") # Append to list of destinations
;;
*)
# Dispatch key=value to the handler for the current section context
getConfig$context
;;
esac

View File

@ -1,30 +1,50 @@
#!/bin/bash
# Copyright © 2012-2026 ScriptFanix
# This program 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.
# This program 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.
# A copy of the GNU General Public License v3 is includded in the LICENSE file
# at the root of the project.
getConfigDestination() {
case "$key" in
'enabled')
# 1 = process this destination, 0 = skip it
destinationenabled["$destination"]="$value"
;;
'path')
# Strip trailing slash for consistency
destinationpath["$destination"]="${value%/}"
;;
'format')
case "$value" in
'mp3')
destinationformat["$destination"]=mp3
# Flag that lame must be present
lameneeded=1
# MP3 can't handfle more than 2 channels
# MP3 can't handle more than 2 channels
[[ -z ${destinationchannels["$destination"]} ]] \
&& destinationchannels["$destination"]=2
;;
'opus')
destinationformat["$destination"]=opus
# Flag that opusenc must be present
opusencneeded=1
;;
'vorbis')
destinationformat["$destination"]=vorbis
# Flag that oggenc must be present
oggencneeded=1
;;
'copy')
# Files are copied/hardlinked as-is
destinationformat["$destination"]=copy
;;
*)
@ -34,6 +54,7 @@ getConfigDestination() {
esac
;;
'quality')
# Vorbis-only: oggenc quality scale (integer, typically 0-10)
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then
@ -46,27 +67,32 @@ getConfigDestination() {
destinationquality["$destination"]="$value"
;;
*)
echo "Invalid parameter \"$key\" for format \"${destinationformat["$destination"]}\"" >&2
echo "Invalid parameter '$key' for" \
"format" \
"'${destinationformat["$destination"]}'" >&2
exit $EFMTINVPARM
;;
esac
;;
'normalize')
# Whether to normalize audio volume (via sox --norm)
case $value in
'true'|'on'|'yes')
'true'|'on'|'yes'|'1')
destinationnormalize["$destination"]=1
;;
'false'|'off'|'no')
'false'|'off'|'no'|'0')
destinationnormalize["$destination"]=0
;;
*)
echo "normalize takes values:" \
"'yes' ,'true' ,'on', 'no', 'false',"\
"'off'"
echo "normalize takes values:" \
"'yes' ,'true' ,'on', '1', 'no'," \
"'false','off', '0'"
;;
esac
;;
'bitrate')
# Opus/MP3: target bitrate in kbps
# integer only; Bash doesn't support floats
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then
@ -88,6 +114,7 @@ getConfigDestination() {
esac
;;
'loss')
# Opus Forward Error Correction: expected packet loss percentage (0-100)
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then
@ -100,12 +127,15 @@ getConfigDestination() {
destinationloss["$destination"]="$value"
;;
*)
echo "$Invalid parameter \"$key\" for format \"${destinationformat["$destination"]}\"" >&2
echo "Invalid parameter '$key' for" \
"format" \
"'${destinationformat["$destination"]}'" >&2
exit $EFMTINVPARM
;;
esac
;;
'channels')
# Up/downmix to this many channels if needed
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then
@ -116,6 +146,7 @@ getConfigDestination() {
destinationchannels["$destination"]=$value
;;
'frequency')
# Resample to this sample rate in Hz (e.g. 44100)
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then
@ -126,21 +157,24 @@ getConfigDestination() {
destinationfrequency["$destination"]=$value
;;
'noresample')
# MP3-only: prevent lame from auto-downsampling at low
# bitrates
case $value in
'true'|'on'|'yes')
'true'|'on'|'yes'|'1')
destinationnoresample["$destination"]=1
;;
'false'|'off'|'no')
'false'|'off'|'no'|'0')
destinationnoresample["$destination"]=0
;;
*)
echo "noresample takes values:" \
"'yes' ,'true' ,'on', 'no', 'false',"\
"'off'"
"'yes' ,'true' ,'on', '1', 'no',"\
"'false','off', '0'"
;;
esac
;;
'rename')
# File rename pattern using %{tag} tokens
case "$value" in
*/*)
destinationrenamepath["$destination"]="${value%/*}"
@ -149,46 +183,62 @@ getConfigDestination() {
destinationrename["$destination"]="${value##*/}"
;;
'fat32compat')
# Strip FAT32-illegal characters (? \ < > : * | ")
# trim spaces/dots
case $value in
'true'|'on'|'yes')
'true'|'on'|'yes'|'1')
destinationfat32compat["$destination"]=1
;;
'false'|'off'|'no')
'false'|'off'|'no'|'0')
destinationfat32compat["$destination"]=0
;;
*)
echo "fat32compat takes values:" \
"'yes' ,'true' ,'on', 'no', 'false',"\
"'off'"
echo "fat32compat takes values:" \
"'yes' ,'true' ,'on', '1', 'no',"\
"'false','off', '0'"
;;
esac
;;
'ascii-only')
# Transliterate Unicode filenames to ASCII using
#Requires Perl Text::Unidecode
case $value in
'true'|'on'|'yes')
'true'|'on'|'yes'|'1')
destinationascii["$destination"]=1
# Signal that the perl coprocess will
# be needed
textunidecodeneeded=1
;;
'false'|'off'|'no')
'false'|'off'|'no'|'0')
destinationascii["$destination"]=0
;;
*)
echo "ascii-only takes values:" \
"'yes' ,'true' ,'on', 'no', 'false',"\
"'off'"
"'yes' ,'true' ,'on', '1', 'no',"\
"'false','off', '0'"
;;
esac
;;
'skip_mime-type')
# Accumulate pipe-separated list of mime patterns to
# exclude entirely
destinationskipmime[$destination]="${destinationskipmime[$destination]:+${destinationskipmime[$destination]}|}$value"
;;
'copy_mime-type')
# Accumulate pipe-separated list of mime patterns to
# copy verbatim (action=2)
destinationcopymime[$destination]="${destinationcopymime[$destination]:+${destinationcopymime[$destination]}|}$value"
;;
'copy_extension')
# Accumulate pipe-separated list of file extensions to
# copy verbatim
destinationcopyext[$destination]="${destinationcopyext[$destination]:+${destinationcopyext[$destination]}|}$value"
;;
'higher-than')
# Only re-encode source files with bitrate ABOVE this
# threshold (kbps)
# Files at or below this bitrate will be
# hardlinked/copied instead
expr='^[0-9]*$'
if ! [[ $value =~ $expr ]]
then

View File

@ -1,7 +1,23 @@
#!/bin/bash
# Copyright © 2012-2026 ScriptFanix
# This program 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.
# This program 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.
# A copy of the GNU General Public License v3 is includded in the LICENSE file
# at the root of the project.
getConfigGeneral() {
case $key in
'max-load')
# Target system 1-minute load average
# concurrency is adjusted to stay near this
expr='^[0-9]*$'
if [[ $value =~ $expr ]]
then
@ -13,6 +29,7 @@ getConfigGeneral() {
unset expr
;;
'load-interval')
# How often (seconds) to adjust worker count
expr='^[0-9]*$'
if [[ $value =~ $expr ]]
then
@ -48,6 +65,7 @@ getConfigGeneral() {
fi
;;
2)
# Best-effort class; niceness 0 (highest) to 7 (lowest)
if [ -n "$niceness" ] \
&& (( niceness >= 0 && niceness <= 7 ))
then
@ -59,10 +77,11 @@ getConfigGeneral() {
fi
;;
3)
# Idle class: only gets I/O when no other process needs it
ionice="ionice -c3 "
;;
*)
echo "Invalid ionice parameters $value"\
echo "Invalid ionice class $value"\
>&2
exit $EIONICE
;;
@ -70,15 +89,23 @@ getConfigGeneral() {
fi
;;
'temporary-directory')
# Directory for
# * SQLite FIFOs
# * intermediate WAV files
# * debug logs
tempdir="$value"
;;
'database')
# Path to the SQLite database file
database="$value"
;;
'skip-timestamp-microsec')
# If non-zero, ignore sub-second precision in file timestamps
# Useful on filesystems that don't preserve microseconds
skip_us_timestamp="$value"
;;
debug)
# Allow config file to raise debug level (but not lower it)
(( value > debug )) && debug=$value
;;
esac

View File

@ -1,10 +1,27 @@
#!/bin/bash
# Copyright © 2012-2026 ScriptFanix
# This program 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.
# This program 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.
# A copy of the GNU General Public License v3 is includded in the LICENSE file
# at the root of the project.
getConfigSource() {
case "$key" in
'path')
# Root directory of music collection to transcode from
sourcepath="$value"
;;
'skip')
# Directory pattern to exclude from scanning
# Multiple 'skip' entries accumulate into this array
skippeddirectories+=( "$value" )
;;
esac

View File

@ -1,6 +1,22 @@
#!/bin/bash
# Copyright © 2012-2026 ScriptFanix
# This program 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.
# This program 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.
# A copy of the GNU General Public License v3 is includded in the LICENSE file
# at the root of the project.
printConfig() {
{
# Build a pipe-delimited table
# 'column -t -s|' will transform into columns
echo "General|Config file|$cffile"
[ -n "$ionice" ] && echo "|IO Nice|$ionice"
cat <<-EOF
@ -12,24 +28,29 @@ printConfig() {
Source|Path|$sourcepath
EOF
# Print skipped directories
# use a continuation prefix after the first
for prune_expression in "${skippeddirectories[@]}"
do
(( printed )) \
(( printed )) \
&& echo -n ' | |' \
|| echo -n ' |Skipped directories|'
echo "$prune_expression"
printed=1
done
unset printed
# Loop over destinations and print their settings
# use the destination name as a key into the associative arrays
for destination in ${destinations[@]}
do
cat <<-EOF
$destination|Path|${destinationpath["$destination"]}
|Enabled|${destinationenabled["$destination"]}
|Format|${destinationformat["$destination"]}
|Quality|${destinationquality["$destination"]}
EOF
# Show format-specific fields
if [[ ${destinationformat["$destination"]} == opus ]]
then
echo " |Expected loss|${destinationloss["$destination"]}"
@ -47,6 +68,7 @@ printConfig() {
|Path Change|${destinationrenamepath["$destination"]}
|File Rename|${destinationrename["$destination"]}
EOF
# Display pipe-separated mime lists: one entry per row
[ -n "${destinationskipmime["$destination"]}" ] \
&& echo " |Skipped mime-types|${destinationskipmime["$destination"]//\|/
| |}"
@ -57,5 +79,5 @@ printConfig() {
&& echo " |Copied extensions|${destinationcopyext["$destination"]//\|/
| |}"
done
}|column -t -s'|'
}|column -t -s'|' # Format as aligned columns using '|' as delimiter
}

View File

@ -1,5 +1,22 @@
#!/bin/bash
# Copyright © 2012-2026 ScriptFanix
# This program 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.
# This program 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.
# A copy of the GNU General Public License v3 is includded in the LICENSE file
# at the root of the project.
# writeConfig() generates a new atom.cfg from the current in-memory settings.
# Output is sent to stdout so callers can redirect it to any config file path.
# Each setting is annotated with a description.
writeConfig() {
cat <<-EOCfg
[general]
@ -47,6 +64,7 @@ path $sourcepath
# * skip <directory>: String. Files in <directory> will be ignored. Note that
# <directory> can be any expression accepted by find.
EOCfg
# Emit one skip line per skipped directory
for dir in "${skippeddirectories[@]}"
do
echo $'skip\t\t\t'"$dir"
@ -55,6 +73,7 @@ path $sourcepath
EOCfg
# Emit one section per configured destination
for destination in "${destinations[@]}"
do
cat <<-EOCfg
@ -190,6 +209,8 @@ bitrate ${destinationquality["$destination"]}
# be included in that destination. For more than one mime-type, use multiple
# times, as needed. The '*' character is a wildcard.
EOCfg
# Emit one skip_mime-type line per MIME pattern (pipe-separated
# in the array)
destinationskipmime["$destination"]="${destinationskipmime["$destination"]}|"
while [[ ${destinationskipmime["$destination"]} =~ \| ]]
do
@ -203,6 +224,7 @@ bitrate ${destinationquality["$destination"]}
# covers and other images to the destination. In fact, AtOM will try to use
# hard links instead of copies.
EOCfg
# Emit one copy_mime-type line per MIME pattern
destinationcopymime["$destination"]="${destinationcopymime["$destination"]}|"
while [[ ${destinationcopymime["$destination"]} =~ \| ]]
do
@ -213,6 +235,7 @@ bitrate ${destinationquality["$destination"]}
# * copy_extension <extension>: Copy files whose name and with ".<extension>"
EOCfg
# Emit one copy_extension line per extension pattern
destinationcopyext["$destination"]="${destinationcopyext["$destination"]}|"
while [[ ${destinationcopyext["$destination"]} =~ \| ]]
do