#!/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]
# This section contains parameters of the program itself.

# * max-load <load>: Integer. Defines how parallel processing will behave. AtOM
#     will try to keep the 1 minute load average between <load> and <load>+1 by
#     adjusting concurrency.
#     Initial concurrency will be set to half of that value.
max-load		$maxload

# * load-interval <seconds>: Integer. How often should we check the load average
#     and adjust concurrency. Set this too low, and concurrency may be increased
#     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.
load-interval		$loadinterval

# * ionice <class> [niceness]: IO-hungry processes will be run with ionice class
#     <class> and niceness [niceness] (if applicable). See man ionice for details.
ionice			$class $niceness

# * 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.
temporary-directory	$tempdir

# * database <file>: String. Where the SQLite database should be stored.
database		$database

# * debug <level>: Integer.
#debug			1

# * skip-timestamp-microsec: Ignore microsecond precision in timestamps.
skip-timestamp-microsec	${skip_us_timestamp:-0}


[source]
# This section defines where are the files you want transcoded.

# * path <directory>: String. The root of your collection.
#     Default: /var/lib/mpd/music
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"
	done
	cat <<-EOCfg


	EOCfg
	# Emit one section per configured destination
	for destination in "${destinations[@]}"
	do
		cat <<-EOCfg
[$destination]
# Each section not named 'general' or 'source' will define a new destination.

# Common parameters:
#  Mandatory parameters:
#   * enabled: Whether or not to treat this destination (1=true/0=false)
enabled			1

#   * path: Where files will be written
path			${destinationpath["$destination"]}

#   * format: copy, ogg, opus or mp3. Other formats may appear in the future -
#   feel free to implement your preferred format.
format			${destinationformat["$destination"]}

		EOCfg
		case "${destinationformat["$destination"]}" in
			vorbis)
				cat <<-EOCfg
# Ogg parameters:
#   * quality <quality>: The quality parameter of oggenc. See man oggenc for
#     more info. This is the only mode supported and planned. Still, if you want
#     to be able to use bitrate settings, feel free to fork and file a pull
#     request.
quality			${destinationquality["$destination"]}


				EOCfg
			;;
			opus)
				cat <<-EOCfg
# Opus parameters:
#   * bitrate <bitrate>: Set (VBR) bitrate to <bitrate>. Note that while Opus
#     allows for decimal values, AtOM does not. The reason for this is simple:
#     we do numeric comparisons, and Bash only manipulates integers.
bitrate			${destinationquality["$destination"]}

#   * loss <percent>: If you intend to stream the resulting files over an
#     unreliable protocol, you may want to make use of Opus' Forward Error
#     Correction algorythm. See the Opus-codec.org website for details.
#     Default: 0
loss			${destinationloss["$destination"]:-0}


				EOCfg
			;;
			mp3)
				cat <<-EOCfg
# MP3 parameters:
#   * bitrate <bitrate>: Set ABR to <bitrate>. Again, if you want CBR or any
#     other mode supported by lame, please fork and file a pull request.
bitrate			${destinationquality["$destination"]}

#   * noresample <yes>/<no>: LAME may decide to encode your file to a lower
#     sampling-rate if you use a low bitrate. Setting this to yes will
#     append --resample <original file's rate>, preventing any resampling from
#     happening.
				EOCfg
				if (( ${destinationnoresample["$destination"]} ))
				then
					echo $'noresample\t\tyes'
				else
					echo $'noresample\t\tno'
				fi
				cat <<-EOCfg


				EOCfg
			;;
		esac
		cat <<-EOCfg
# Optional parameters:
#   * normalize <yes>/<no>: Normalize output files.
		EOCfg
		if (( ${destinationnormalize["$destination"]} ))
		then
			echo $'normalize\t\tyes'
		else
			echo $'normalize\t\tno'
		fi
		cat <<-EOCfg

#   * rename <string>: Destination files will be named according to <string>,
#     after expansion of special strings:
#       %{album},
#       %{albumartist},
#       %{artist},
#       %{disc},
#       %{genre},
#       %{releasecountry},
#       %{title},
#       %{track},
#       %{year}.
#     Untagged files or files in unrecognized formats will not be changed.
		EOCfg
		if [[ ${destinationrenamepath["$destination"]}/${destinationrename["$destination"]} == / ]]
		then
			echo $'#rename\t\t\t<pattern>'
		elif [[ ${destinationrenamepath["$destination"]}/${destinationrename["$destination"]} == /* ]]
		then
			echo $'rename\t\t\t'"${destinationrename["$destination"]}"
		else
			echo $'rename\t\t\t'"${destinationrenamepath["$destination"]}/${destinationrename["$destination"]}"
		fi
		cat <<-EOCfg

#   * fat32compat <yes>/<no>: Rename files for compatibility with FAT32
#     filesystems.
		EOCfg
		if (( ${destinationfat32compat["$destination"]} ))
		then
			echo $'fat32compat\t\tyes'
		else
			echo $'fat32compat\t\tno'
		fi
		cat <<-EOCfg

#   * ascii-only <yes>/<no>: Rename files for compatibility with ASCII-only
#     systems.
		EOCfg
		if (( ${destinationascii["$destination"]} ))
		then
			echo $'ascii-only\t\tyes'
		else
			echo $'ascii-only\t\tno'
		fi
		cat <<-EOCfg

#   * skip_mime-type <mime-type>: Files with mime-type <mime-type> will not
#     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
			echo $'skip_mime-type\t\t'"${destinationskipmime["$destination"]%%|*}"
			destinationskipmime["$destination"]="${destinationskipmime["$destination"]#*|}"
		done
		cat <<-EOCfg

#   * copy_mime-type <mime-type>: Same as skip_mime-type, except that files
#     matching will be copied as-is to the destination. E.g. image/* will copy
#     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
			echo $'copy_mime-type\t\t'"${destinationcopymime["$destination"]%%|*}"
			destinationcopymime["$destination"]="${destinationcopymime["$destination"]#*|}"
		done
		cat <<-EOCfg

#   * 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
			echo $'copy_extension\t\t'"${destinationcopyext["$destination"]%%|*}"
			destinationcopyext["$destination"]="${destinationcopyext["$destination"]#*|}"
		done
		cat <<-EOCfg

#   * channels <number>: Files with more than <number> channels will be
#     downmixed. Useful if you create files for telephony music-on-hold.
		EOCfg
		if (( ${destinationchannels["$destination"]} ))
		then
			echo $'channels\t\t'${destinationchannels["$destination"]}
		else
			echo $'#channels\t\t2'
		fi
		cat <<-EOCfg

#   * frequency <hertz>: Files will be resampled as needed to <hertz>Hz
#     sampling-rate. Shoutcast/Icecast streams require a constant sampling-rate.
#     Telephony systems often require a sample rate of 8000Hz.
		EOCfg
		if (( ${destinationfrequency["$destination"]} ))
		then
			echo $'frequency\t\t'${destinationfrequency["$destination"]}
		else
			echo $'#frequency\t\t44100'
		fi
		cat <<-EOCfg

#   * higher-than <bitrate>: Integer. Only reencode files with bitrates higher
#     then <bitrate>kbps. This only applies if sample-rate, channel count and of
#     course format are equal. If unset, only files with bitrates equal to that
#     of the target will be copied (actually, hardlinking will be attempted
#     first). As Ogg Vorbis target quality is not defined by its bitrate, Ogg
#     Vorbis files will always be reencoded if unset.
		EOCfg
		if (( ${destinationmaxbps["$destination"]} ))
		then
			echo $'higher-than\t\t'${destinationmaxbps["$destination"]}
		else
			echo $'#higher-than\t\t128'
		fi
		cat <<-EOCfg


		EOCfg
	done
}
