#!/bin/bash -e
# @GOM_COPYRIGHT@
#
# Configuration script for gom


#
# VARIABLES
#
gomconfig_test_gombinary="/usr/bin/gom-ct"
# '--initialize' should do
# a) a normal gom startup with all conf files loaded and
# b) an initialization with conf.initialize loaded.
gomconfig_test_gomoptions="--initialize"
gomconfig_test_gomverbosity=2

# config dir names
gomconfig_confdir_sys=/etc/gom ;
if test `whoami` == root;
    then gomconfig_confdir_user=/etc/gom ;
    else gomconfig_confdir_user=${HOME}/.gom ;
fi

# relative config file names
gomconfig_conffile_default_mixer=conf.default_mixer
gomconfig_conffile_initialize=conf.initialize
gomconfig_conffile_gom=conf.gom

# config defaults
gomconfig_default_default_mixer="-d/dev/mixer"
gomconfig_default_initialize="-d/dev/mixer -G"
gomconfig_default_gom="# Discouraged to use any option here."

# status texts
gomconfig_status_flag_ok="Ok              "
gomconfig_status_flag_configured="Configured      "
gomconfig_status_flag_using_sysconf="Using sysconf   "
gomconfig_status_flag_unconfigured="Unconfigured    "
gomconfig_status_flag_unknown="Status unknown  "
gomconfig_status_flag_error="Error           "

#
# README: about this script
#
gomconfig_readme ()
{
	clear
	echo "README"
	echo "======"
	echo " This configuration script assumes a correctly installed and configured"
	echo "sound driver. If you are using this as part of package configuration"
	echo "(especially when installing from scratch with a default kernel), you"
	echo "possibly need to fix the sound driver first, and rerun this script"
	echo "($0) later."
	echo " The characters before the config choices mean _M_andatory, _R_ecommended, "
	echo "_O_ptional and _D_iscouraged."
	echo
	gomconfig_break
}

#
# COMMON HELPERS
#

# pause before continuing
gomconfig_break ()
{
	echo -n "Hit RETURN to continue..."; read
}

#
# Scan for Obsolete conffiles
#
# 1: filename (relative)
gomconfig_scanobsolete_file ()
{
	if [ -e ${gomconfig_confdir_user}/$1 ] ;
		then echo "Found obsolete configuration file $1"
		rm -i ${gomconfig_confdir_user}/$1 ;
	else echo "$1 not found, ok..."
	fi
}

gomconfig_scanobsolete ()
{
	clear
	echo "Scanning for obsolete files from version 0.29.10 (or older):"
	echo
	gomconfig_scanobsolete_file gomrc
	gomconfig_scanobsolete_file default
	echo
	echo "Please delete (or rename to <mixer>.<oldname>) settings files"
	echo "from 0.29.10 (or older) versions manually."
	echo
	gomconfig_break
}


gomconfig_noconfdir ()
{
	if [ ! -d ${gomconfig_confdir_user} ];
		then echo
		echo "Sorry, you need the gom configuration dir (2) first."
		echo
		gomconfig_break
		return 0;
	fi
	return 1;
}

# 1: Relative filename.
# 2: Default value.
# 3: Loaded.
# 4: Restrictions.
# 5: Provides.
# 6: Title.
gomconfig_conffile_editor ()
{
	# test for config dir
	if gomconfig_noconfdir ;
		then return 0;
	fi
	conffile=${gomconfig_confdir_user}/$1
	default=$2

	# ok, headline
	clear
	echo "$6"
	echo "==========="

	echo " File        : ${conffile}"
	echo " Default     : ${default}"
	echo " Loaded      : $3"
	echo " Restrictions: $4"
	echo " Provides    : $5"
	echo
	echo "-->Current value:"
	if test -e ${conffile} ;
		then cat ${conffile}
	else echo "--no file--"
	fi
	echo "<--Stop current value."
	echo
	echo " [RETURN]: Cancel     (don't touch anything)."
	echo " d       : Default    (use stubborn default '${default}')."
	echo " e       : Edit       (edit config. via EDITOR=${EDITOR})."
	echo " l       : Line input (custom config. via line read)."
	echo " P       : Purge      (remove configuration file)."
	echo
	echo -n "Your choice: "; read choice
	echo
	if test "${choice}" == "d" ;
		then echo -n "Writing defaults to '${conffile}'..."
		echo "${default}" >${conffile}
	elif test "${choice}" == "P"
		then echo -n "Purging '${conffile}'..."
		rm -f ${conffile}
	elif test "${choice}" == "l"
		then echo -n "Enter custom options: "
		read options_custom
		echo -n "Writing custom options to '${conffile}'..."
		echo ${options_custom} >${conffile}
	elif test "${choice}" == "e"
		then ${EDITOR} ${conffile} || true
		echo -n "Extern editing..."
	else echo -n "Not touching anything..."
	fi
	echo "done."
	echo
	gomconfig_break
}

# 1: filename
# 2: sys file name
gomconfig_conffile_status ()
{
	conffile=${gomconfig_confdir_user}/$1
	conffile_sys=${gomconfig_confdir_sys}/$1

	if test -e ${conffile} ;
		then echo -n "${gomconfig_status_flag_configured}${conffile}."
	elif test `whoami` != root -a -e ${conffile_sys} ;
		then echo -n "${gomconfig_status_flag_using_sysconf}${conffile_sys}."
	else echo -n "${gomconfig_status_flag_unconfigured}No file."
	fi
}



#
# TESTS
#

# this function unifies the testing command && recalculates it everytime (rather than a fix var)
gomconfig_test_cmd ()
{
	echo "${gomconfig_test_gombinary} --verbose=${gomconfig_test_gomverbosity} ${gomconfig_test_gomoptions}"
}

# This is only for viewing purposes
gomconfig_test ()
{
	clear
	echo "Testing configuration"
	echo "====================="
	echo
	echo "-->Running test command: `gomconfig_test_cmd`:"
	echo
	`gomconfig_test_cmd` || true
	echo
	echo "<--Test output stop."
	echo
	gomconfig_break
}

gomconfig_test_status ()
{
	if `gomconfig_test_cmd` >/dev/null 2>&1 ;
		then echo -n "${gomconfig_status_flag_ok}No errors in test run."
		return 0
	else echo -n "${gomconfig_status_flag_error}Some errors in test run."
		return 1
	fi
}

#
# 1. AUDIO USERS
#

# a recursive helper
gomconfig_audio_users_add ()
{
	if test -e /etc/debian_version ;
		then echo
		echo "'<user> [RETURN]': Add user to group audio."
		echo "'[RETURN]'       : Quit adding users."
		echo
		echo -n "Add user: "
		read user
		if test ! "${user}" == "" ;
			then adduser ${user} audio ;
			gomconfig_audio_users_add ;
		fi
	else echo "This is not Debian GNU/Linux."
		echo "I don't know the recommended way to give users audio access on this system."
		echo "You need to figure this out by yourself."
	fi
}

# yet another (not yet recursive) helper
gomconfig_audio_users_del ()
{
	if test -e /etc/debian_version;
		then echo
		echo "Sorry -- I don't yet know a reasonable and recommended"
		echo "way to delete a user from a certain group in Debian GNU/Linux."
		echo "Please do this manually."
	else echo
		echo "This is not Debian GNU/Linux."
		echo "I don't know the recommended way to deny users audio access on this system."
		echo "You need to figure this out by yourself."
	fi
}

# text output of status
gomconfig_audio_users_status ()
{
	# Test for Debian
	if test ! -e /etc/debian_version;
		then echo -n "${gomconfig_status_flag_unknown}This is not Debian GNU/Linux.";
	else if test `whoami` == root ;
		then if grep --quiet "^audio:.*:.*:$" /etc/group ;
			then echo -n "${gomconfig_status_flag_error}No user in group audio."
		else echo -n "${gomconfig_status_flag_ok}At least one user in group audio."
		fi
	else if grep --quiet "^audio.*`whoami`" /etc/group ;
		then echo -n "${gomconfig_status_flag_ok}`whoami` is audio user."
	else echo -n "${gomconfig_status_flag_error}`whoami` is _not_ audio user."
	fi
	fi
	fi
}

gomconfig_audio_users ()
{
	clear
	echo "Audio users"
	echo "==========="
	echo " Adding a user to the group 'audio' is the recommended way (at least"
	echo "in Debian GNU/Linux) to grant a user to 'do sound', including"
	echo "controlling the soundcard mixer(s) with gom."
	echo
	echo    "[RETURN] : Cancel  (don't touch current settings)."
	echo    "0        : Add     (add user(s) to group audio)."
	echo    "1        : Delete  (delete user(s) from group audio)."
	echo
	echo -n "Current status: "; gomconfig_audio_users_status; echo
	echo -n "Current value : "; grep audio /etc/group || true
	echo
	if test `whoami` == root ;
		then echo -n "Your choice: "; read choice
		echo
		if test "${choice}" == "0" ;
			then gomconfig_audio_users_add
		elif test "${choice}" == "1"
			then gomconfig_audio_users_del
		else echo
			echo "Not touching anything...done."
		fi
	else echo "These system settings can only be changed by root."
	fi
	echo
	gomconfig_break
}

#
# 2. CONFIG DIR
#

gomconfig_config_dir_fatal_error ()
{
	echo
	echo "Fatal error: configuration directory invalid."
	echo "Because    : '${gomconfig_confdir_user}' exists, but is not a directory."
	echo "Please correct this manually, then rerun this script."
	echo
	exit 1;
}

gomconfig_config_dir_status ()
{
	if test -e ${gomconfig_confdir_user} ;
		then if test ! -d ${gomconfig_confdir_user} ;
			then echo -n "${gomconfig_status_flag_error}${gomconfig_confdir_user} is not a directory (fatal)!"
		else echo -n "${gomconfig_status_flag_ok}${gomconfig_confdir_user} exists."
		fi
	else echo -n "${gomconfig_status_flag_unconfigured}No config dir."
	fi
}

gomconfig_config_dir_purge ()
{
	echo
	if [ -e ${gomconfig_confdir_user} ] ;
		then if [ ! -d ${gomconfig_confdir_user} ] ;
			then gomconfig_config_dir_fatal_error
		else echo -n "Making temporary backup..."
			purge_backup_dir=/tmp/gomconfig_purge_backup.$$
			cp -a ${gomconfig_confdir_user} ${purge_backup_dir}
			echo "done."
			echo
			echo "If this was a mistake, you can manually retrieve the purged"
			echo "configuration from '${purge_backup_dir}'."
			echo
			echo -n "Purging ${gomconfig_confdir_user}..."
			rm -rf ${gomconfig_confdir_user}
		fi
	else echo -n "Nothing to purge..."
	fi
}

gomconfig_config_dir ()
{
	clear
	echo "Configuration directory"
	echo "======================="
	echo " The configuration files of gom are stored in '${gomconfig_confdir_user}', so"
	echo "its existence is mandatory for any further configuration."
	echo
	echo "Current status: `gomconfig_config_dir_status`"
	echo
	echo " [RETURN] : Cancel  (don't touch anything)."
	echo " c        : Create  (add directory if non-existent)."
	echo " P        : Purge   (remove configuration directory)."
	echo
	echo -n "Your choice: "; read choice
	echo
	if test "${choice}" == "c" ;
		then if test -e ${gomconfig_confdir_user} ;
			then if test ! -d ${gomconfig_confdir_user} ;
				then gomconfig_config_dir_fatal_error
			else echo -n "Leaving existing '${gomconfig_confdir_user}' untouched..."
			fi
		else echo -n "Creating configuration directory '${gomconfig_confdir_user}'..."
			mkdir -ma=rx,u+w ${gomconfig_confdir_user}
		fi

	elif test "${choice}" == "P"
		then gomconfig_config_dir_purge
	else echo
		echo -n "Not touching anything..."
	fi
	echo "done."
	echo
	gomconfig_break
}

#
# 3. DEFAULT MIXER
#

gomconfig_default_mixer ()
{
	gomconfig_conffile_editor "${gomconfig_conffile_default_mixer}" \
		"${gomconfig_default_default_mixer}" \
		"On every startup of gom." \
		"Restricted to '-d<mixer-device-file>'." \
		"Implicit opening of a mixer device." \
		"Default Mixer"
}


#
# 4. DEFAULT SETTINGS
#

# text output of status
gomconfig_default_settings_status ()
{
	echo -n "${gomconfig_status_flag_unknown}n/a."
}

gomconfig_default_settings ()
{
	if gomconfig_noconfdir ;
		then return 0;
	fi

	clear
	echo "Default settings"
	echo "================"
	echo " Default setting can be loaded via '-G, --get-settings' (with the"
	echo "mixer in question opened)."
	echo
	echo " Please choose a mixer device to edit/create a default setting for."
	echo
	echo " [RETURN] : Cancel        (don't touch anything)."
	echo " d        : /dev/mixer    (the default mixer)."
	echo " <n>      : /dev/mixer<n> (the <n>th mixer - <n> only one digit)."
	echo " c        : Some other strange device file name."
	echo
	echo -n "Your choice: "; read choice
	echo
	device_file=cancelled
	if test "${choice}" == "d" ;
		then device_file=/dev/mixer
	elif test "${choice}" == "0" || test "${choice}" == "1" || test "${choice}" == "2" || \
		test "${choice}" == "3" || test "${choice}" == "4" || test "${choice}" == "5" || \
		test "${choice}" == "6" || test "${choice}" == "7" || test "${choice}" == "8" || \
		test "${choice}" == "9" ;
		then device_file=/dev/mixer${choice}
	elif test "${choice}" == "c"
		then echo -n "Give (complete) device file name: "; read device_file
		echo
	fi
	if test "${device_file}" == "cancelled" ;
		then echo "Not touching anything...done."
	else echo "About to edit default mixer settings for '${device_file}' using"
		echo "gom's interactive interface; existing settings are preloaded, and"
		echo "changes automatically saved after quitting (use 'q')."
		echo
		gomconfig_break
		echo
		if ${gomconfig_test_gombinary} --ignore-config --device=${device_file} --get-settings --interface=t --save-settings ;
			then echo
			echo "Extern settings editing successful.";
		else echo
			echo "Some errors while editing...";
		fi
	fi
	echo
	gomconfig_break
}


#
# 5. INITIALIZATION
#

gomconfig_initialize ()
{
	gomconfig_conffile_editor "${gomconfig_conffile_initialize}" \
		"${gomconfig_default_initialize}" \
		"With the option '-O, --originate, --initialize'." \
		"Unrestricted." \
		"Creation of an initialization routine, even for multiple mixers." \
		"Initialize"
}

#
# 5. GOM
#

gomconfig_gom ()
{
	gomconfig_conffile_editor "${gomconfig_conffile_gom}" \
		"${gomconfig_default_gom}" \
		"On every startup of gom." \
		"Restricted to '-v, -q, -F, -U'." \
		"Implicit creation of certain bevaviours. Discouraged." \
		"Gom"
}

#
# Main Loop
#
gomconfig_mainloop ()
{
	selection='none'
	until test "${selection}" == "q" -o "${selection}" == "Q" ; do

		clear
		echo    "                Configuring tool for @PACKAGE@-@VERSION@";
		echo    "==========================================================================="
		if test `whoami` == root ;
			then echo "                Changing SYSTEM configuration.";
		else echo "             Changing user configuration for `whoami`.";
		fi
		echo    "---------------------------------------------------------------------------"
		echo    "1: M-Audio users       `gomconfig_audio_users_status`"
		echo    "2: R-Config dir        `gomconfig_config_dir_status`"
		echo    "3: R-Default mixer     `gomconfig_conffile_status ${gomconfig_conffile_default_mixer}`"
		echo    "4: O-Default settings  `gomconfig_default_settings_status`"
		echo    "5: O-Initialization    `gomconfig_conffile_status ${gomconfig_conffile_initialize}`"
		echo    "6: D-Gom rc file       `gomconfig_conffile_status ${gomconfig_conffile_gom}`"
		echo    "---------------------------------------------------------------------------"
		echo    "t: Test                `gomconfig_test_status`"
		echo    "s: Scan obsolete       Scan for obsolete configuration files."
		echo    "==========================================================================="
		echo -n "q,Q: Quit  r: Readme  v: Log verbosity (${gomconfig_test_gomverbosity})              Your choice: "; read selection
		if   test "${selection}" == "1"; then gomconfig_audio_users
		elif test "${selection}" == "2"; then gomconfig_config_dir
		elif test "${selection}" == "3"; then gomconfig_default_mixer
		elif test "${selection}" == "4"; then gomconfig_default_settings
		elif test "${selection}" == "5"; then gomconfig_initialize
		elif test "${selection}" == "6"; then gomconfig_gom
		elif test "${selection}" == "r"; then gomconfig_readme
		elif test "${selection}" == "v"; then echo; echo -n "New Verbosity: "; read gomconfig_test_gomverbosity
		elif test "${selection}" == "t"; then gomconfig_test
		elif test "${selection}" == "s"; then gomconfig_scanobsolete
		fi
	done
}

###############
# Start code
#

if test "$1" == "--force" || ( test "$1" == "" && ! gomconfig_test_status )
	then gomconfig_mainloop
elif test "$1" == "--version"
	then echo "This gomconfig came with @PACKAGE@-@VERSION@."
elif test "$1" == "--purge"
	then gomconfig_config_dir_purge
	echo "done."
elif test "$1" == ""
	then echo
	echo "Use '$0 --force' to reconfigure."
else echo
	echo "Usage: $0 [--version | --force | --purge]"
	echo
	echo "'--version' gives version information."
	echo "'--force'   forces reconfiguration."
	echo "'--purge'   removes config dir (currently: ${gomconfig_confdir_user})"
	echo "            completely (temporary backup)."
fi

#
# Get the exit status right
#
`gomconfig_test_cmd` >/dev/null 2>&1
