#!/bin/dash
# Specify the sink and source for aloopd
# This file always writes to $HOME/.aloopdrc, never to /etc/aloopd.conf
#
# Copyright (C) James Budiono 2021, 2022, 2023, 2024
# License: GPL Version 3 or later
#

### configuration
APPTITLE="ALSA Loop Server Configuration"
APPTITLE_MAIN="$APPTITLE"
APPTITLE_LOCALSINK="Computer >--> Speaker"
APPTITLE_LOCALSOURCE="Mic >--> Computer"
APPTITLE_NETSOURCE="Computer >--> Network"
APPTITLE_NETSINK="Network >--> Computer"

OUTFILE=$HOME/.aloopdrc
RESTART_DELAY=${RESTART_DELAY:-10} # in seconds, usually it's enough
ASOUNDRC=${ASOUNDRC:-$HOME/.asoundrc} # it can easily be /etc/asound.conf for system-wide settings
JACKP_CNAME="aloopd" # persistent jack client name so it is recognisable on JACK graph
ALOOPD_OUT="${ALOOPD_OUT:-hw:Loopback,1,6}" # this is what fatdog-default-soundcard.sh uses for aloopd
JACKP_LOOP_NET="${JACKP_LOOP_NET:-4}" # see allocation in fatdog-default-soundcard.sh


DEFAULT_TRX_PORT=1350
DEFAULT_LATENCY=500
AVAIL_LATENCIES="
	50 \"50ms - better audio/video sync\"
	150 \"150ms - somewhere in between\"
	500 \"500ms - lighter CPU load\"
	other \"Other - specify yourself\"
"

ALOOPD_DEVICES="
	aloopd \"aloopd - exclusive output (better latency)\"
	aloopdshared \"aloopdshared - shared output (can be used for recording mixout) \"
"

NETSINK_DEVICES="
	default \"Default computer speaker\"
	aloopd \"Default computer mic input\"
"

########## UI helpers #########

# $1-info
msgbox() {
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --msgbox "$1" 0 0 10000
	else
		dialog --backtitle "$APPTITLE" --msgbox "$1" 0 0 > /dev/stderr
	fi
}

# $1-info $2-timeout (in ms)
infobox() {
	local timeout=${2:-10000}
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --infobox "$1" 0 0 $timeout
	else
		dialog --backtitle "$APPTITLE" --no-cancel --pause "$1" 12 60 $(( timeout/1000 )) > /dev/stderr
	fi
}

# $1-text, $2-choices, output: stdout
choices() {
	if [ $DISPLAY ]; then
		eval Xdialog --title \"$APPTITLE\" --stdout --no-tags --menubox \""$1"\" 20 100 5 $2
	else 
		eval dialog --backtitle \"$APPTITLE\" --stdout --no-tags --menu \""$1"\" 0 0 0 $2
	fi
}

# $1-text, $2-choices, output: stdout
multi_choices() {
	if [ $DISPLAY ]; then
		eval Xdialog --title \"$APPTITLE\" --stdout --no-tags --separator \" \" --checklist \""$1"\" 20 100 5 $2
	else
		eval dialog --title \"$APPTITLE\" --stdout --no-tags --separator \" \" --checklist \""$1"\" 0 0 0 $2
	fi
}

# $1-text
yesno() {
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --yesno "$1" 0 0
	else
		dialog --title "$APPTITLE" --yesno "$1" 0 0
	fi
}

# $1-text
noyes() {
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --defaultno --yesno "$1" 0 0
	else
		dialog --title "$APPTITLE" --defaultno --yesno "$1" 0 0
	fi
}

# $1-prompt, $2-current value
inputbox() {
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --stdout --inputbox "$1" 0 0 "$2"
	else
		dialog --title "$APPTITLE" --stdout --inputbox "$1" 0 0 "$2"		
	fi
}

# $1-prompt
fselect() {
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --backtitle "$1" --stdout --no-buttons --fselect "$PWD" 0 0
	else
		dialog --title "$APPTITLE" --backtitle "$1" --stdout --fselect "$PWD" 10 70
	fi
}

# $1-prompt
tailbox() {
	local tmpfile=/tmp/bt-status.$$
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --no-cancel --backtitle "$1" --tailbox - 0 0
	else
		cat > $tmpfile
		dialog --title "$APPTITLE" --backtitle "$1" --textbox $tmpfile 0 0
		rm $tmpfile
	fi
}

# $1-text
splash() {
	if [ "$XPID" ]; then
		kill $XPID
		XPID=
	fi

	if [ "$1" ]; then	
		if [ $DISPLAY ]; then
			Xdialog --title "$APPTITLE" --no-buttons --infobox "$1" 0 0 1000000 &
			XPID=$!
		else
			dialog --backtitle "$APPTITLE" --infobox "$1" 0 0 > /dev/stderr
		fi
	fi
}

# $1-text
die() {
	infobox "$1"
	exit 1
}

die_unchanged() {
	die "Operation cancelled. Nothing was changed."
}

# $1-option, $* options
has_option() {
	local p inp=$1
	shift
	for p; do
		case $p in
			$inp) return 0
		esac	
	done
	return 1
}


########## Task helpers ############

# out: PLAYBACK_DEVICES RECORD_DEVICES BT_DEVICES LOCAL_PLAYBACK_DEVICES LOCAL_RECORD_DEVICES
detect_hardware() {
	PLAYBACK_DEVICES=$(LANG=C aplay -l | awk '$1~/card/ && $0!~/Loopback/ { print "\"" $0 "\" " "\"" $0 "\"" }')
	RECORD_DEVICES=$(LANG=C arecord -l | awk '$1~/card/ && $0!~/Loopback/ { print "\"" $0 "\" " "\"" $0 "\"" }')
	LOCAL_PLAYBACK_DEVICES=
	LOCAL_RECORD_DEVICES=

	if pidof jackd > /dev/null; then
		PLAYBACK_DEVICES="$PLAYBACK_DEVICES jack \"ALSA -> JACK bridge (auto-connect)\""
		RECORD_DEVICES="$RECORD_DEVICES jack \"JACK -> ALSA bridge (auto-connect)\""

		# manual/persistent versions of the above
		PLAYBACK_DEVICES="$PLAYBACK_DEVICES jackp \"ALSA -> JACK bridge (persistent)\""
		RECORD_DEVICES="$RECORD_DEVICES jackp \"JACK -> ALSA bridge (persistent)\""

		if type zita-a2j > /dev/null; then
			PLAYBACK_DEVICES="$PLAYBACK_DEVICES zita \"ALSA -> JACK bridge (persistent) using zita\""
			RECORD_DEVICES="$RECORD_DEVICES zita \"JACK -> ALSA bridge (persistent) using zita\""
		fi
		
		PLAYBACK_DEVICES="$PLAYBACK_DEVICES jacka \"ALSA -> JACK bridge (persistent) using audioadapter \""
		RECORD_DEVICES="$RECORD_DEVICES jacka \"JACK -> ALSA bridge (persistent) using audioadapter\""
	fi

	if pidof pulseaudio > /dev/null; then
		LOCAL_PLAYBACK_DEVICES="$LOCAL_PLAYBACK_DEVICES pulse \"ALSA -> PulseAudio bridge\""
		LOCAL_RECORD_DEVICES="$LOCAL_RECORD_DEVICES pulse \"PulseAudio -> ALSA bridge\""
	fi

	if pidof pipewire > /dev/null; then
		LOCAL_PLAYBACK_DEVICES="$LOCAL_PLAYBACK_DEVICES pipewire \"ALSA -> Pipewire bridge\""
		LOCAL_RECORD_DEVICES="$LOCAL_RECORD_DEVICES pipewire \"Pipewire -> ALSA bridge\""
	fi	

	if pidof bluetoothd > /dev/null && BT_DEVICES=$(bt-device -l);
	then
		BT_DEVICES="$(echo "$BT_DEVICES" | sed '1d; s|.*(\(.*\))|"\1" "&"|')"
		PLAYBACK_DEVICES="$PLAYBACK_DEVICES bluetooth \"Bluetooth devices\""
		RECORD_DEVICES="$RECORD_DEVICES bluetooth \"Bluetooth devices\""
	fi
}

# see if trx package is installed
has_trx() {
	# hopefully this is reliable enough ... 
	ls /var/log/packages/trx-* > /dev/null 2>&1
}

# $1-extra text out: LATENCY (in ms)
get_latency() {
	LATENCY=$(choices "Choose latency $1" "$AVAIL_LATENCIES") || die_unchanged
	if [ "$LATENCY" = other ]; then
		LATENCY=$(inputbox "Specify the latency in milliseconds.

If the latency is too big you will notice audio/video out of sync.
If the latency is too small you will either hear choppy sound, or nothing at all.

500 (500ms = 0.5 second) helps with slower machine and slower devices (e.g. Bluetooth)
50 (50ms = 0.05 second) provides unnoticeable delay
Use larger values if you use 'aloopdshared' as output

" "$DEFAULT_LATENCY") || die_unchanged
	fi
}

# get trx ip and port
# $1-send/recv, out: TRX_IP and TRX_PORT
get_trx_ip_port() {
	local msgip= msgport= 
	case $1 in
		send)
			msgip="Specify remote machine IP address to send the audio to (cannot be blank):"
			msgport="Specify remote machine port number (default is $DEFAULT_TRX_PORT):"
			;;
			
		recv)
			msgip="Specify listening IP address (for multicast - can be left empty otherwise):"
			msgport="Specify listening port number (default is $DEFAULT_TRX_PORT):"
			;;
	esac

	while true; do
		TRX_IP=$(inputbox "$msgip" ) || die_unchanged
		case $1 in
			send)
				if [ -z "$TRX_IP" ]; then
					msgbox "Remote machine IP cannot be blank!"
					continue
				fi
		esac
		[ "$TRX_IP" ] && TRX_IP="-h $TRX_IP"

		TRX_PORT=$(inputbox "$msgport" "$DEFAULT_TRX_PORT") || die_unchanged		
		if [ "$TRX_PORT" = "$DEFAULT_TRX_PORT" ]; then
			TRX_PORT= # if same as default port, leave it blank
		fi
		[ "$TRX_PORT" ] && TRX_PORT="-p $TRX_PORT"
		break
	done
}

# get JACK period and nperiod
# out: PERIOD and NPERIOD
get_period() {
	PERIOD= NPERIOD=
	if PERIOD=$(inputbox "Enter the frames/period you set in JACK server (e.g. 64)"); then
		NPERIOD=$(inputbox "Enter the periods/buffer you set in JACK server (e.g. 3)")
	fi
}

# $1-commen $2-job
JOBNUM=1 # start at 1
set_job() {
	local comment="$1" job="$2"
	#echo JOB$JOBNUM=\'$job\'
	#echo JOBCOMMENT$JOBNUM=\'$comment\'
	eval JOB$JOBNUM='$job'
	eval JOBCOMMENT$JOBNUM='$comment'
	JOBNUM=$(( JOBNUM + 1 ))
}

# $1-card, $2-type (Playback/Capture, if blank, get all mixers)
get_mixers() {
	amixer -D $1 controls | awk -F, "/MIXER/ && \$0~/$2/ {gsub(/'/,\"'\\\\''\",\$3); print \"-m \\\"\" \$3 \"\\\"\"}"
}

########## Configuration tasks ############

AUDIOADAPTER_LOCAL_USED=
# out: JOBx BT_DEV
localsink() {
	local SOURCE= SINK= LATENCY= MIXERS=
	APPTITLE="$APPTITLE_LOCALSINK"

	msgbox "Configuring $APPTITLE"

	SOURCE=$(choices "Choose audio source to use" "$ALOOPD_DEVICES") || die_unchanged
	detect_hardware # detect hardware just before it is used	
	SINK=$(choices "Choose output device" "$PLAYBACK_DEVICES $LOCAL_PLAYBACK_DEVICES") || die_unchanged
	case "$SINK" in
		bluetooth)
			BT_DEV=$(choices "Choose bluetooth devices for output" "$BT_DEVICES") || die_unchanged
			SINK="bluealsa_raw:SRV=org.bluealsa,DEV=$BT_DEV,PROFILE=A2DP,DELAY=0"
			
			# this is the correct way to do it but it doesn't work for bluealsa at the moment
			# perhaps one day it will
			#if yesno "Redirect mixer controls from bluealsa?"; then
			#	# we can't get mixer if we aren't connected
			#	bt-device -c "$BT_DEV"
			#	MIXERS=$(get_mixers bluealsa Playback)
			#fi

			# instead, replace the .asoundrc
			sed -i -e '/^ctl.!default.*bluealsa/d' $ASOUNDRC
			echo "ctl.!default bluealsa" >> $ASOUNDRC
			;;
		jack|pulse|pipewire)
			#noyes "Apply sample converter for $SINK for better compatibility?" && # always if we don't use it
			SINK="plug:$SINK"
			;;
		jackp)
			# nothing to setup
			;;
		zita|jacka)
			SOURCE=$ALOOPD_OUT
			;;
		*)
			SINK=$(echo $SINK | sed 's/card \([0-9]*\):.*device \([0-9]*\):.*/hw:\1,\2/')
			sed -i -e '/^ctl.!default.*bluealsa/d' $ASOUNDRC
			yesno "Redirect mixer controls from $SINK?" && MIXERS=$(get_mixers ${SINK%%,*} Playback)
			noyes "Apply sample converter for $SINK for better compatibility?" && SINK="plug$SINK"
			;;
	esac

	# job setup
	case $SINK in
		jackp)
			set_job "localsink: computer -> persistent jack" \
				"start-stop-daemon -S -b -n $JACKP_CNAME-in -a $JACKP_CNAME-in -x alsa_in -- -d $SOURCE -j $JACKP_CNAME-in"	
			;;
		zita)
			set_job "localsink: computer -> persistent jack (zita)" \
				"start-stop-daemon -S -b -n $JACKP_CNAME-in -a $JACKP_CNAME-in -x zita-a2j -- -L -d $SOURCE -j $JACKP_CNAME-in"
			;;
		jacka)
			get_period
			if [ "$PERIOD" ] && [ "$NPERIOD" ]; then
				AUDIOADAPTER_LOCAL_USED=1
				set_job "localsink: computer -> persistent jack (audioadapter)" \
					"jack_load $JACKP_CNAME audioadapter -i \"-d $SOURCE -p$PERIOD -n$NPERIOD\""
			fi
			;;
		*)
			get_latency
			set_job "localsink: computer -> speaker/bt" \
				"alsaloop -t $((LATENCY * 1000)) -T -1 -S none -C $SOURCE -P $SINK $MIXERS -d"		
			;;
	esac

	APPTITLE="$APPTITLE_MAIN"
}

# out: JOBx
localsource() {
	local SOURCE= SINK= LATENCY= MIXER=
	APPTITLE="$APPTITLE_LOCALSOURCE"

	msgbox "Configuring $APPTITLE"

	detect_hardware # detect hardware just before it is used
	SOURCE=$(choices "Choose mic source" "$RECORD_DEVICES $LOCAL_RECORD_DEVICES") || die_unchanged
	case "$SOURCE" in
		bluetooth)
			BT_DEV=$(choices "Choose bluetooth devices for output" "$BT_DEVICES") || die_unchanged
			;;
		jack|pulse|pipewire)
			#noyes "Apply sample converter for $SOURCE for better compatibility?" && # always fail if we don't use it
			SOURCE="plug:$SOURCE"
			;;
		jackp)
			# nothing to setup
			;;
		zita|jacka)
			SINK=$ALOOPD_OUT
			;;
		*)
			SOURCE=$(echo $SOURCE | sed 's/card \([0-9]*\):.*device \([0-9]*\):.*/hw:\1,\2/')
			# redirecting mixer here doesn't work. it only causes stuttering when recording.
			# remove it for now. maybe one day it will be fixed.
			#yesno "Redirect mixer controls from $SOURCE?" && MIXERS=$(get_mixers ${SOURCE%%,*} Capture)
			noyes "Apply sample converter for $SOURCE for better compatibility?" && SOURCE="plug$SOURCE"
			;;
	esac
	[ -z "$SINK" ] && SINK="aloopd" # no choice, always aloopd

	# job setup
	case "$SOURCE" in
		bluetooth)
			get_latency
			set_job "localsource: bt -> computer" \
				"start-stop-daemon -S -b -x bluealsa-aplay -- --profile-sco --pcm-buffer-time=$((LATENCY * 1000)) -D $SINK $BT_DEV"
			;;
		jackp)
			set_job "localsource: persistent jack -> computer" \
				"start-stop-daemon -S -b -n $JACKP_CNAME-out -a $JACKP_CNAME-out -x alsa_out -- -d $SINK -j $JACKP_CNAME-out"
			;;
		zita)
			set_job "localsource: persistent jack -> computer (zita)" \
				"start-stop-daemon -S -b -n $JACKP_CNAME-out -a $JACKP_CNAME-out -x zita-j2a -- -L -d $SINK -j $JACKP_CNAME-out"
			;;
		jacka)
			if [ -z "$AUDIOADAPTER_LOCAL_USED" ]; then
				get_period
				if [ "$PERIOD" ] && [ "$NPERIOD" ]; then 
				set_job "localsink: computer -> persistent jack (audioadapter)" \
					"jack_load $JACKP_CNAME audioadapter -i \"-d $SINK -p$PERIOD -n$NPERIOD\""
				fi
			fi
			;;			
		*)
			get_latency
			set_job "localsource: mic -> computer" \
				"alsaloop -t $((LATENCY * 1000)) -T -1 -S none -C $SOURCE -P $SINK $MIXERS -d"
			;;
	esac

	APPTITLE="$APPTITLE_MAIN"
}


# out: JOBx
AUDIOADAPTER_NET_USED=
netsource() {
	local SOURCE= TRX_IP= TRX_PORT=
	APPTITLE="$APPTITLE_NETSOURCE"	
	if ! has_trx; then
		msgbox "Install trx package first."
		APPTITLE="$APPTITLE_MAIN"
		return
	fi

	msgbox "Configuring $APPTITLE"

	detect_hardware # detect hardware just before it is used
	SOURCE=$(choices "Choose audio/mic source" "$ALOOPD_DEVICES $RECORD_DEVICES") || die_unchanged
	case "$SOURCE" in
		aloopd*|jackp|zita|jacka) ;; # nothing to setup
		jack) SOURCE=jackp;; # doesn't work, so change to jackp
		bluetooth)
			BT_DEV=$(choices "Choose bluetooth devices for output" "$BT_DEVICES") || die_unchanged
			;;
		*)
			SOURCE=$(echo $SOURCE | sed 's/card \([0-9]*\):.*device \([0-9]*\):.*/hw:\1,\2/')
			noyes "Apply sample converter for $SOURCE for better compatibility?" && SOURCE="plug$SOURCE"
			;;
	esac

	# job setup
	case "$SOURCE" in
		bluetooth)
			# pull from bt and pump to alsa - replace sink and source
			# we have to use 22-bluealsa-aplay.conf helper (two loopbacks are used)
			SINK="bluealsa-aplay:PROFILE=sco" 
			SOURCE="bluetooth_sco_capture"
			get_latency "for bluetooth"			
			set_job "netsource - bt pull: bt -> computer" \
				"start-stop-daemon -S -b -x bluealsa-aplay -- --profile-sco --pcm-buffer-time=$((LATENCY * 1000)) -D $SINK $BT_DEV"
			;;
		jackp)
			# pull from jack and pump to alsa - replace sink and source
			SINK="hw:Loopback,1,$JACKP_LOOP_NET"			
			SOURCE="plughw:Loopback,0,$JACKP_LOOP_NET"
			set_job "netsource - jack pull: jack -> computer" \
				"start-stop-daemon -S -b -n $JACKP_CNAME-net-out -a $JACKP_CNAME-net-out -x alsa_out -- -d $SINK  -j $JACKP_CNAME-net-out"
			;;
		zita)
			# pull from jack and pump to alsa - replace sink and source
			SINK="hw:Loopback,1,$JACKP_LOOP_NET"			
			SOURCE="plughw:Loopback,0,$JACKP_LOOP_NET"
			set_job "netsource - jack pull: jack -> computer (zita)" \
				"start-stop-daemon -S -b -n $JACKP_CNAME-net-out -a $JACKP_CNAME-net-out -x zita-j2a -- -L -d $SINK  -j $JACKP_CNAME-net-out"
			;;
		jacka)
			# pull from jack and pump to alsa - replace sink and source
			get_period
			SINK="hw:Loopback,1,$JACKP_LOOP_NET"			
			SOURCE="plughw:Loopback,0,$JACKP_LOOP_NET"
			if [ "$PERIOD" ] && [ "$NPERIOD" ]; then
				AUDIOADAPTER_NET_USED=1
				set_job "netsource - jack pull: jack -> computer (audioadapter)" \
					"jack_load $JACKP_CNAME-net audioadapter -i \"-d $SINK -p$PERIOD -n$NPERIOD\""
			fi			
			;;
	esac
	get_trx_ip_port send	
	get_latency "for network"
	set_job "netsource: computer -> network" \
		"tx -d $SOURCE -m $LATENCY $TRX_IP $TRX_PORT -D /dev/null"

	APPTITLE="$APPTITLE_MAIN"
}

# out: JOBx BT_DEV
netsink() {
	local SOURCE= SINK= LATENCY=
	APPTITLE="$APPTITLE_NETSINK"
	if ! has_trx; then
		msgbox "Install trx package first."
		APPTITLE="$APPTITLE_MAIN"
		return
	fi

	msgbox "Configuring $APPTITLE"

	detect_hardware # detect hardware just before it is used
	SINK=$(choices "Choose output device" "$NETSINK_DEVICES $PLAYBACK_DEVICES") || die_unchanged
	case "$SINK" in
		aloopd*|default|jackp|zita|jacka) ;; # nothing to setup
		jack) SINK=jackp;; # doesn't work, so change to jackp
		bluetooth)
			BT_DEV=$(choices "Choose bluetooth devices for output" "$BT_DEVICES") || die_unchanged
			SINK="bluealsa_raw:SRV=org.bluealsa,DEV=$BT_DEV,PROFILE=A2DP,DELAY=0"					
			;;
		*)
			SINK=$(echo $SINK | sed 's/card \([0-9]*\):.*device \([0-9]*\):.*/hw:\1,\2/')
			noyes "Apply sample converter for $SINK for better compatibility?" && SINK="plug$SINK"
			;;
	esac

	# job setup
	case "$SINK" in
		jackp)
			# pull from alsa and then pump to jack - replace sink and source
			SINK="plughw:Loopback,0,$JACKP_LOOP_NET"
			SOURCE="hw:Loopback,1,$JACKP_LOOP_NET"
			set_job "netsink - jack push: computer -> jack" \
				"start-stop-daemon -S -b -n $JACKP_CNAME-net-in -a $JACKP_CNAME-net-in -x alsa_in -- -d $SOURCE  -j $JACKP_CNAME-net-in"
		;;
		zita)
			# pull from alsa and then pump to jack - replace sink and source
			SINK="plughw:Loopback,0,$JACKP_LOOP_NET"
			SOURCE="hw:Loopback,1,$JACKP_LOOP_NET"
			set_job "netsink - jack push: computer -> jack (zita)" \
				"start-stop-daemon -S -b -n $JACKP_CNAME-net-in -a $JACKP_CNAME-net-in -x zita-a2j -- -L -d $SOURCE  -j $JACKP_CNAME-net-in"
		;;
		jacka)
			# pull from jack and pump to alsa - replace sink and source
			SINK="plughw:Loopback,0,$JACKP_LOOP_NET"
			SOURCE="hw:Loopback,1,$JACKP_LOOP_NET"			
			if [ -z "$AUDIOADAPTER_NET_USED" ]; then
				get_period
				if [ "$PERIOD" ] && [ "$NPERIOD" ]; then
					set_job "netsink - jack push: computer -> jack (audioadapter)" \
						"jack_load $JACKP_CNAME-net audioadapter -i \"-d $SOURCE -p$PERIOD -n$NPERIOD\""
				fi
			fi
			;;
	esac

	get_trx_ip_port recv
	get_latency "for network"
	set_job "netsink: network -> computer/bt" \
		"rx -d $SINK -m $LATENCY -j $LATENCY $TRX_IP $TRX_PORT -D /dev/null"

	APPTITLE="$APPTITLE_MAIN"
}

# output all the jobs to the config file
output_config_file() {
	# write output
	{
		cat << EOF
# For template/examples/notes, see /etc/aloopd.conf

RESTART_DELAY='$RESTART_DELAY'
MAXJOBS='$((JOBNUM - 1))'
JACKP_CNAME='$JACKP_CNAME'

# Bluetooth device to connect
BT_DEV='$BT_DEV'

EOF
		# output jobs and comments
		for p in $(seq 1 $(( JOBNUM - 1)) ); do
			echo "# $(eval echo \$JOBCOMMENT$p)"
			echo JOB$p=\'"$(eval echo \$JOB$p)"\'
			echo
		done
	
	} > $OUTFILE
}



########### main ############

AVAIL_TASKS="
	localsink   \"Computer >--> Local Speaker\" on
	localsource \"Local Mic >--> Computer\" off
	netsource   \"Computer/Mic >--> Network\" off
	netsink     \"Network >--> Computer/Mic\" off
"

TASKS=$(multi_choices "Choose what you want to configure" "$AVAIL_TASKS") || die_unchanged
[ -z "$TASKS" ] && die_unchanged

for TASK in $TASKS; do
	case $TASK in
		localsink)   localsink ;;
		localsource) localsource ;;
		netsource)   netsource ;;
		netsink)     netsink ;;
	esac
done

# Done, but if service is up, we need to stop it before writing the new config
if service aloopd status | grep -q running; then
	splash "Stopping aloopd before updating config ..."
	service aloopd stop
	output_config_file

	splash "Config updated, now waiting $RESTART_DELAY seconds to release ALSA resources before restarting ..."
	sleep $RESTART_DELAY
	splash ""

	service aloopd start
	infobox "aloopd is re-started.

Config file is written to $OUTFILE.
"

else
	# server not running, so write config file and offer to start the service
	output_config_file
	if yesno "Config saved.

Do you want to start/restart aloopd service?
";  then
		service aloopd start
		infobox "aloopd is started.

Config file is written to $OUTFILE.
"
	else
		infobox "
Config file is written to $OUTFILE.
"
	fi
fi

# finish.
