#!/bin/sh
# {{{ Copyright
# Soma - a command line/dialog radio player
#
# Copyright 2010 David Woodfall <dave@dawoodfall.net>
# All rights reserved.
# Copyright modifications Patrick Volkerding, with thanks.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Thanks to Patrick Volkerding for the mktemp patch.

# }}}
# {{{ cursor on/off
cursor()
{
	# Need to use xterm-color to make dialog colours correct
	# but cursor won't turn off with xterm-color
	TERM=xterm-256color
	setterm -cursor $1
	TERM=xterm-color
}
# }}}
# {{{ Init
init() {
	trap "cleanup" HUP INT ABRT QUIT SEGV TERM KILL PIPE STOP TSTP

	SOMAROOT=$(mktemp -d /tmp/soma-XXXXXX)
	STATIONS=$SOMAROOT/soma-stations
	MSTATUS=$SOMAROOT/soma-mstatus
	STATUS=$SOMAROOT/soma-status
	PLAYING=$SOMAROOT/soma-playing
	TMP=$SOMAROOT/soma-tmp
	FIFO=$SOMAROOT/soma.fifo
	MIXERS=$SOMAROOT/mixers
	SOMAOPTIONS=~/.soma/options.conf
	DEFSTATIONS=/etc/soma/stations.conf
	USRSTATIONS=~/.soma/stations.conf
	SAVEDLIST=~/.soma/savedlist
	SCHEDULES=~/.soma/schedules
	TIME=$(date +"%H:%M")
	DATE=$(date +"%Y%m%d")
	export DIALOGRC=~/.soma/defaultsrc

	rm -f $MIXER $STATIONS $MSTATUS $STATUS $TMP
	touch $STATUS

	# Make our local dirs
	[ ! -d ~/.soma/themes ] &&  mkdir -p ~/.soma/themes

	# Copy the global options if local doesn't exist
	[ ! -r $SOMAOPTIONS ] && cat /etc/soma/options.conf > $SOMAOPTIONS

	# Copy themes to local dir
	for theme in $(ls /etc/soma/themes)
	do
		[ ! -r ~/.soma/themes/$theme ] && \
		cat /etc/soma/themes/$theme > ~/.soma/themes/$theme
	done

	if [ -z "$(grep DIALOGOPTS= $SOMAOPTIONS)" ]; then
		echo "
# Dialog colours in titles or not
# Set to \"\" for no colour and also unset TITCOL.
# Default = \"--colors\"
DIALOGOPTS=\"--colors\"" >> $SOMAOPTIONS
	fi

	if [ -z "$(grep SETVOL= $SOMAOPTIONS)" ]; then
		echo "
# Saved volume from last session
SETVOL=\"50 50\"" >> $SOMAOPTIONS
	fi

	if [ -z "$(grep CACHE= $SOMAOPTIONS)" ]; then
		echo "
# MPlayer cache. Default 320
CACHE=320" >> $SOMAOPTIONS
	fi

	if [ -z "$(grep SAVE_LIST_AT_QUIT= $SOMAOPTIONS)" ]; then
		echo "
# Save the track list automatically when quitting. Default 0
SAVE_LIST_AT_QUIT=0" >> $SOMAOPTIONS
	fi

	if [ -z "$(grep TITCOL= $SOMAOPTIONS)" ]; then
		echo "
# TITCOL - Dialog Title Colour
# This setting controls the dialog title colour separate to the
# dialogrc file if needed.
#
# By default it is set to \"\Zb\" (bold default dialog foreground colour).
# You can mix bold and colour by eg: \"\Zb\Z4\" etc. See man dialog for
# more info.
#
# Colours are set by \Zn where n =:
#
# 0 black
# 1 red
# 2 green
# 3 yellow
# 4 blue
# 5 magenta
# 6 cyan
# 7 white
# 8 default dialogrc foreground
#
# These are xterm colours. Your terminal may have a different mind.
TITCOL=\"\Zb\"" >> $SOMAOPTIONS

	fi

	if [ -z "$(grep CONNECTTIMEOUT= $SOMAOPTIONS)" ]; then
		echo "
# CONNECTTIMEOUT (Connection Timeout)
#
# This controls how long soma will wait for a stream before giving up.
# If you have problems with your internet you may want to adjust it.
# Default: 150
CONNECTTIMEOUT=150" >> $SOMAOPTIONS
	fi

	source /etc/soma/options.conf
	source $SOMAOPTIONS
	touch $SCHEDULES

	CARDINDEX=$(echo $OUTCARD | cut -d= -f3 | cut -d, -f1)
	if [ "$CARDINDEX" = "" ]; then CARDINDEX="0"; fi

	let index=0

	count=$(aplay -l | grep "^card" | wc -l)
	printf "aplay -l lists $count device(s):\n"
	aplay -l | grep "^card" > $TMP 

	DEVICE[0]="pulse"
	DEVICE[1]="alsa"

	for card in $(seq 2 $((count+1)))
	do
		SOUNDCARD[$card]=$(head -n $((card-1)) $TMP | tail -n 1)
		printf "$card ${SOUNDCARD[card]}\n"
		major=$(echo "${SOUNDCARD[card]}" | cut -d: -f1 | sed 's/^card //')
		minor=$(echo "${SOUNDCARD[card]}" | cut -d: -f2 | sed 's/device //')
		minor=$(echo ${minor: -2} | sed 's/ //')
		DEVICE[$card]="device=hw=$major,$minor"
		HWDEVICE[$card]=${SOUNDCARD[card]}
	done

	NUMDEVICES=$card

	DEVICE[$((card+1))]="jack"
	DEVICE[$((card+2))]="NAS"

	STATIONLIST="$(cat $USRSTATIONS $DEFSTATIONS \
		| sed 's# ,#,#
				s#, #,#
				s# $##
				s#^#\"#
				s#,#\" \"#
				s#$#\" \\#;')"


	cat $USRSTATIONS $DEFSTATIONS \
		| sed 's# ,#,#;s#, #,#;s#^\s+##;s#\s+$##' \
		> $STATIONS

	cursor off
}
# }}}
# {{{ Command line
get_commandline() {
	until [ -z "$1" ]
	do
		[ "$1" == "-h" ] && usage && exit
		[ "$1" == "-v" ] && version
		[ "$1" == "--version" ] && version
		[ "$1" == "-d" ] && DEBUG="1"
		shift
	done
}
# }}}
# {{{ Version
version() {
	echo "Soma $VERSION"
	exit
}
# }}}
# {{{ Usage

usage() {
cat << EOF
Soma $VERSION
A dialog + mplayer radio player.

Key commands supported in status window:

(       Volume -5
)       Volume +5
1 - 0   Volume 10%, 20%, ... 100% (saved)
Space   Pause/Play
d       Disconnect/Reconnect
a       Add schedule
b       Station browser
m       Mute toggle
s       Scheduler
o       Options
t       Change theme
q       Quit

Config Files:

~/.soma/options.conf	    Options file.
~/.soma/stations.conf	    User radio station list.
~/.soma/themes/*rc  	    Colours for dialog.
~/.soma/schedules	    Saved schedules.

EOF
return
}
# }}}
# {{{ Cleanup/exit
cleanup() {
	if [ $SAVE_LIST_AT_QUIT -eq 1 ]; then
		cat $STATUS >> $SAVEDLIST
		echo >> $SAVEDLIST
	fi

	kill $MPLAYERPID 2>/dev/null
	rm -fr $SOMAROOT

	cursor on
	exit 0
}
# }}}
# {{{ Save tracklist
save() {
	let rows=$(stty size | cut -f1 -d' ')
	let cols=$(stty size | cut -f2 -d' ')
	cat $STATUS >> $SAVEDLIST
	echo >> $SAVEDLIST
	dialog --title "Saved Tracks" \
		--msgbox "Tracks list appended to $SAVEDLIST" $rows $cols
}
# }}}
# {{{ Mainmenu
mainmenu() {
	cursor off

	while true
	do
		let rows=$(stty size | cut -f1 -d' ')
		let cols=$(stty size | cut -f2 -d' ')
		if [ -z "$DEBUG" ]; then
			dialog --cancel-label Quit $DIALOGOPTS --menu "${TITCOL}Main Menu" \
				$rows $cols $rows \
				"Station" "Choose a Station" \
				"Status" "Playing Now" \
				"Mixer" Mixer \
				"Scheduler" Scheduler \
				"Output" "Choose Sound Device" \
				"Choose Mixer" "Choose Mixer Device" \
				"Save" "Save Track List" \
				"Options" "Manually Edit Options" \
				"Quit" "Quit Soma" \
				2> $TMP

			[ $? -ne 0 ] && cleanup
		else
			dialog --cancel-label Quit $DIALOGOPTS --menu "${TITCOL}Soma $VERSION" \
				$rows $cols $rows \
				"Station" "Choose a Station" \
				"Status" "Playing Now" \
				"Mixer" Mixer \
				"Scheduler" Scheduler \
				"Output" "Choose Sound Device" \
				"Choose Mixer" "Choose Mixer Device" \
				"Save" "Save Track List" \
				"Options" "Manually Edit Options" \
				"Debug" "Raw MPlayer Output" \
				"Quit" "Quit Soma" \
				2> $TMP

			[ $? -ne 0 ] && cleanup
		fi

		main=$(cat $TMP)

		[ "$main" == "Mixer" ] && mixerpanel
		[ "$main" == "Station" ] && stationselector
		[ "$main" == "Status" ] && status
		[ "$main" == "Scheduler" ] && schedule_main
		[ "$main" == "Output" ] && selectoutput
		[ "$main" == "Choose Mixer" ] && selectmixer
		[ "$main" == "Save" ] && save
		[ "$main" == "Options" ] && edit_options
		[ "$main" == "Quit" ] && cleanup
		[ "$main" == "Debug" ] && rawstatus
	done
}
# }}}
# {{{ Play
play()
{
	source $SOMAOPTIONS

	if [ -n "$(pgrep -x mplayer | grep $MPLAYERPID 2>/dev/null)" ]; then
		kill $MPLAYERPID
	fi

	OLDCHANNEL=$CHANNEL
	rm -f $MSTATUS
	rm -f $FIFO
	mkfifo $FIFO

	# Radio 3 seems to have much lower output level than the others
	# This should balance it out by boosting volume
	if [ -n "$AFFILTER" ] && [ "$CHANNEL" = "BBC Radio 3" ]; then
		VOL="$AFFILTER"
	else
		unset VOL
	fi

	unset PLAYLIST

	[ -n "$(echo $STATIONURL \
		| grep -P '\.(pls|m3u|ram|asx|wvx|m3u8)')" ] \
		&& PLAYLIST="-playlist"

	[ -n "$SETVOL" ] && VOL="-volume $SETVOL"

	mplayer -ao $OUTCARD -slave -input file=$FIFO -msglevel all=4 \
		$PLAYLIST "$STATIONURL" -cache $CACHE \
		$SOFTVOL $VOL >> $MSTATUS 2>/dev/null &

	MPLAYERPID=$!

	dialog $DIALOGOPTS --title "${TITCOL}Status" --timeout 1 --msgbox \
		"Connecting to $CHANNEL ..."  $rows $cols 2> /dev/null
}
# }}}
# {{{ Setup
# setup the info. loop until we have some
# this is really to shorten the title loop
setup() {
	touch $MSTATUS
	unset TITLE
	unset COUNT

	# wait for info to appear
	while [ -z "$(grep 'AUDIO' $MSTATUS)" ]
	do
		sleep 0.1
		let COUNT=$((COUNT+1))
		if [ -z "$(ps ux | grep $MPLAYERPID | grep -v grep)" ]; then
			dialog $DIALOGOPTS --title "${TITCOL}Status" --ok-label "Main Menu" \
				--msgbox "No stream!" $rows $cols
			lasttitle="Idle"
			unset laststation
			CHANNEL="Idle"
			mainmenu
		fi
		if [ $COUNT -gt $CONNECTTIMEOUT ]; then
			dialog $DIALOGOPTS --title "${TITCOL}Status" --ok-label "Main Menu" \
				--msgbox "Connection timeout occurred.\n\
If your internet connection is slow, \
you may want to try\nadjusting the CONNECTTIMEOUT \
value in ~/.soma/options.conf." $rows $cols
			lasttitle="Idle"
			unset laststation
			CHANNEL="Idle"
			mainmenu
		fi
	done

	if [ -z "$TITLE" ]; then
		TITLE=$(grep StreamTitle $MSTATUS | cut -d\; -f1 | cut -d= -f2 | tail -n 1)
	fi
	if [ -z "$TITLE" ]; then
		TITLE=$(grep name $MSTATUS | cut -d: -f2 | tail -n 1)
	fi
	if [ -z "$TITLE" ]; then
		TITLE=$(grep title $MSTATUS | cut -d: -f2 | tail -n 1)
	fi

	TITLE="${TITLE/#\'/}"
	TITLE="${TITLE/%\'/}"
	TITLE="${TITLE/#Now playing:/}"
	TITLE="${TITLE/# /}"
	TITLE="${TITLE//  / }"

	while [ -n "$(echo $TITLE | grep "| |")" ]
	do
		TITLE="${TITLE//| |/|}"
	done

	if [ -z "$TITLE" ]; then
		TITLE=$(echo "$STATIONLIST" | grep -w "$STATIONURL" 2>/dev/null | head -n 1 | \
			cut -d'"' -f2)
	fi

	# Note: piping to 'xargs echo' is a bit of a hack that works like perl's chomp
	# There may be better ways to do this. Answers on a postcard please!

	NAME="$(grep -i Name $MSTATUS | tail -n 1 | cut -d: -f2- | xargs echo)"
	[ -n "$NAME" ] && echo "Name      : $NAME" >> $STATUS
	GENRE="$(grep Genre $MSTATUS | tail -n 1 | cut -d: -f2- | xargs echo)"
	[ -n "$GENRE" ] && echo "Genre     : $GENRE" >> $STATUS
	WEBSITE="$(grep Website $MSTATUS | tail -n 1 | cut -d: -f2- | xargs echo)"
	[ -n "$WEBSITE" ] && echo "Website   : $WEBSITE" >> $STATUS
	BITRATE="$(grep Bitrate $MSTATUS | tail -n 1 | cut -d: -f2- | xargs echo)"
	[ -n "$BITRATE" ] && echo "Bitrate   : $BITRATE" >> $STATUS
	AUTHOR="$(grep -i author $MSTATUS | tail -n 1 | cut -d: -f2- | xargs echo | sed 's/^author/Author/')"
	[ -n "$AUTHOR" ] && echo "Author    : $AUTHOR" >> $STATUS
	COPY="$(grep -i copyright $MSTATUS | tail -n 1 | cut -d: -f2- | xargs echo | sed 's/^copy/Copy/')"
	[ -n "$COPY" ] && echo "Copyright : $COPY" >> $STATUS
	AUDIO="$(grep AUDIO $MSTATUS | tail -n 1 | cut -d: -f2- | xargs echo | sed 's/^AUDIO/Audio/')"
	[ -n "$AUDIO" ] && echo "Audio     : $AUDIO" >> $STATUS
	echo "Title     : $TITLE" >> $STATUS
	echo "$CHANNEL:$TITLE" >  $PLAYING

	lasttitle=$TITLE
}
# }}}
# {{{ Current title
title() {
	unset TITLE

	TITLE="$(grep StreamTitle $MSTATUS | cut -d\; -f1 | cut -d= -f2 | tail -n 1)"
	if [ -z "$TITLE" ]; then
		TITLE="$(grep name $MSTATUS | cut -d: -f2 | tail -n 1)"
	fi
	if [ -z "$TITLE" ]; then
		TITLE="$(grep title $MSTATUS | cut -d: -f2 | tail -n 1)"
	fi

	TITLE="${TITLE/#\'/}"
	TITLE="${TITLE/%\'/}"
	TITLE="${TITLE/#Now playing:/}"
	TITLE="${TITLE/# /}"
	TITLE="${TITLE//  / }"

	while [ "$(echo $TITLE | grep '| |')" != "" ]
	do
		TITLE="${TITLE//| |/|}"
	done

	if [ -z "$TITLE" ]; then
		TITLE="$(grep name $MSTATUS | cut -d: -f2 | tail -n 1)"
	fi

	[ -z "$TITLE" ] && TITLE="$CHANNEL"

	if [ -z "$TITLE" ]; then
		TITLE=$(grep $STATIONURL $STATIONS 2>/dev/null | head -n 1 | \
			cut -d, -f1 | cut -d: -f2-)
	fi

	if [ -z "$(ps ux | grep $MPLAYERPID | grep -v grep)" ]; then
		lasttitle="Idle"
		unset laststation
		CHANNEL="Idle"
	fi

}
# }}}
# {{{ Status
status() {
	cursor off

	let rows=$(stty size | cut -f1 -d' ')
	let cols=$(stty size | cut -f2 -d' ')

	dialog $DIALOGOPTS --exit-label "Back" --keep-window --timeout 1 \
		--title "${TITCOL}[$TIME] $CHANNEL" --tailbox $STATUS $rows $cols 2> $TMP

	while (true)
	do
		let rows=$(stty size | cut -f1 -d' ')
		let cols=$(stty size | cut -f2 -d' ')

		if [ -n "$MPLAYERPID" ]; then
			if [ -z "$(pgrep -x mplayer | grep $MPLAYERPID 2>/dev/null)" ]; then
				dialog $DIALOGOPTS --title "${TITCOL}Status" \
				 --yes-label "Main Menu" --no-label "Reconnect" \
				 --yesno "Lost the stream!" $rows $cols

				if [ $? -eq 1 ]; then
					CHANNEL=$OLDCHANNEL
					echo >> $STATUS
					play
					setup
					status
				else
					lasttitle="Idle"
					TITLE="Idle"
					unset laststation
					unset MPLAYERPID
					CHANNEL="Idle"
					mainmenu
				fi

			fi
		fi

		lasttime=$TIME
		TIME=$(date +"%H:%M")
		DATE=$(date +"%Y%m%d")
		FULLDAY=$(date +"%a")
		DAY=${FULLDAY:0:2}

		if [ "$TIME" != "$lasttime" ]; then
			SCHEDCHAN=$(grep "[*,$DATE],$TIME" $SCHEDULES | cut -d, -f3)
			if [ -n "$SCHEDCHAN" ] && [ "$SCHEDCHAN" != "$CHANNEL" ]; then
				schedule_change_station
			else
				SCHEDCHAN=$(grep "$DAY,$TIME" $SCHEDULES | cut -d, -f3)
				if [ -n "$SCHEDCHAN" ] && [ "$SCHEDCHAN" != "$CHANNEL" ]; then
					schedule_change_station
				fi
			fi
		fi

		if [ "$TITLE" != "$lasttitle" ] || [ "$TIME" != "$lasttime" ]; then
			if [ "$TITLE" != "$lasttitle" ]; then
				echo -n "Title     : " >> $STATUS
				echo "$TITLE" >> $STATUS
				echo "$CHANNEL:$TITLE" > $PLAYING
			fi

			dialog $DIALOGOPTS --exit-label "Back" --keep-window --timeout 1 \
				--title "${TITCOL}[$TIME] $CHANNEL" --tailbox $STATUS $rows $cols \
				2> $TMP
			exitwound=$?

			[ $exitwound -eq 0 ] && mainmenu
			[ $exitwound -eq 255 ] && [ -z "$(cat $TMP)" ] && mainmenu
		fi

		input
		lasttitle="$TITLE"
	done
}
# }}}
# {{{ Input
input() {
	unset REPLY
	read -sn1 -t1

	[ $? -ne 0 ] && return

	case $REPLY in
		' ')
			echo "pause"  > $FIFO
			[ "$CHANNEL" == "Paused" ] && CHANNEL=$OLDCHANNEL || CHANNEL="Paused"
			status
		;;

		'd')
			if [ "$CHANNEL" = "Idle" ]; then
				if [ -n "$OLDCHANNEL" ]; then
					CHANNEL=$OLDCHANNEL
					echo >> $STATUS
					play
					setup
					status
				fi
			else
				kill $MPLAYERPID
				unset MPLAYERPID
				CHANNEL="Idle"
				status
			fi
		;;
		'')
			mainmenu
		;;
		'(')
			[ "$SOFTVOL" == "-softvol" ] && echo "volume -50"  > $FIFO
		;;
		')')
			[ "$SOFTVOL" == "-softvol" ] && echo "volume +50"  > $FIFO
		;;
		'1')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="10 10"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO

			fi
		;;
		'2')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="20 20"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO
			fi
		;;
		'3')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="30 30"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO
			fi
		;;
		'4')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="40 40"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO
			fi
		;;
		'5')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="50 50"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO
			fi
		;;
		'6')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="60 60"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO
			fi
		;;
		'7')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="70 70"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO
			fi
		;;
		'8')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="80 80"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO
			fi
		;;
		'9')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="90 90"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO
			fi
		;;
		'0')
			if [ "$SOFTVOL" = "-softvol" ]; then
				SETVOL="100 100"
				sed -i "s/SETVOL=\".*\"/SETVOL=\"$SETVOL\"/" $SOMAOPTIONS
				echo "volume $SETVOL"  > $FIFO
			fi
		;;

		'm')
			echo "mute" > $FIFO
		;;
		'q')
			cleanup
		;;
		'b')
			stationselector
		;;
		's')
			schedule_main
			status
		;;
		'a')
			schedule_add
			status
		;;
		'h')
			help
			status
		;;
		'OQ')
			stationselector
		;;
		'o')
			edit_options
			status
		;;
		't')
			theme
			status
		;;
		*)
		;;
	esac
}
# }}}
# {{{ Halp!
help()
{
	clear
	usage
	echo "Any key to return"
	read -sn1
}
# }}}
# {{{ Raw status
rawstatus() {
	while (true)
	do
		let rows=$(stty size | cut -f1 -d' ')
		let cols=$(stty size | cut -f2 -d' ')

		if [ -z "$MPLAYERPID" ]; then
			dialog $DIALOGOPTS --title "${TITCOL}Status" --msgbox "No stream!" $rows $cols
			return
		fi

		dialog $DIALOGOPTS --exit-label "Back" --keep-window --timeout 1 \
			--title "${TITCOL}$CHANNEL" --tailbox $MSTATUS $rows $cols 2> $TMP
		exitwound=$?

		[ $exitwound -eq 0 ] && return
		[ $exitwound -eq 255 ] && [ -z "$(cat $TMP)" ] && return

		input
		lasttitle="$TITLE"
	done
}

# }}}
# {{{ Station selector
stationselector() {
	let rows=$(stty size | cut -f1 -d' ')
	let cols=$(stty size | cut -f2 -d' ')

	OLDCHANNEL=$CHANNEL

	# sh -c properly sends the quoted strings to dialog
	sh -c "dialog $DIALOGOPTS --menu \"${TITCOL}Stations\" $rows $cols $rows \
		$STATIONLIST" 2> $TMP

	[ $? -ne 0 ] && return

	CHANNEL="$(cat $TMP)"
	STATIONURL=$(echo "$STATIONLIST" | grep -w "$CHANNEL" | cut -d'"' -f4 | head -n 1)

	for (( i=45; i>35; i-- ))
	do
		[ "${CHANNEL:$i:1}" == " " ] && CHANNEL="${CHANNEL:0:$i}" && break
	done

	[ "$STATIONURL" == "$laststation" ] && status

	touch $STATUS

	[ -n "$(cat $STATUS)" ] && echo >> $STATUS

	play
	setup

	laststation=$STATIONURL

	[ -n "$DEBUG" ] && rawstatus || status
}

# }}}
# {{{ Select soundcard
selectoutput() {
	let rows=$(stty size | cut -f1 -d' ')
	let cols=$(stty size | cut -f2 -d' ')
	lasttitle=$TITLE
	unset CARDLIST
	tmp=$OUTCARD
	status="off"

	[ "$tmp" == "pulse" ] && status="on" || status="off"
	CARDLIST="0 \"Pulseaudio.\" $status "
	[ "$tmp" == "alsa" ] && status="on" || status="off"
	CARDLIST+="1 \"Alsa default softmix.\" $status "

	for i in $(seq 2 $NUMDEVICES)
	do
		[ "$OUTCARD" == "alsa:${DEVICE[i]}" ] && status="on" || status="off"
		CARDLIST+="$i \"alsa:${HWDEVICE[i]}\" $status "
	done

	[ "$tmp" == "jack" ] && status="on" || status="off"
	CARDLIST="$CARDLIST $((i+1)) \"Jack.\" $status "

	[ "$tmp" == "NAS" ] && status="on" || status="off"
	CARDLIST="$CARDLIST $((i+2)) \"NAS.\" $status "

	sh -c "/usr/bin/dialog $DIALOGOPTS --radiolist \"${TITCOL}Output Panel\" \
		$rows $cols $rows $CARDLIST 2> $TMP"

	[ $? -ne 0 ] && return

	let RESULT=$(cat $TMP)

	if [ $RESULT -eq 0 ]; then
		OUTCARD="pulse"
	elif [ $RESULT -eq 1 ]; then
		OUTCARD="alsa"
	elif [ $RESULT -eq $((i+1)) ]; then
		OUTCARD="jack"
	elif [ $RESULT -eq $((i+2)) ]; then
		OUTCARD="NAS"
	else
		OUTCARD="alsa:${DEVICE[RESULT]}"
	fi

	if [ -z "$(grep OUTCARD $SOMAOPTIONS)" ]; then
		echo "# Output Card" >> $SOMAOPTIONS
		echo "OUTCARD=\"$OUTCARD\"" >> $SOMAOPTIONS
	else
		sed -i "s/OUTCARD=\"$tmp\"/OUTCARD=\"$OUTCARD\"/" $SOMAOPTIONS
	fi

	[ "$OUTCARD" == "$tmp" ] && return
	[ -z "$TITLE" ] && [ "$TITLE" != "Idle" ] && return
	play
	status
}
# }}}
# {{{ Select mixer card
selectmixer() {
	let rows=$(stty size | cut -f1 -d' ')
	let cols=$(stty size | cut -f2 -d' ')

	unset MIXLIST
	let NUMMIXER=0
	let tmp=$MIXER
	status="off"

	aplay -l | grep card | cut -d, -f1 | sort -u > $MIXERS

	while read card
	do
		[ $tmp -eq $NUMMIXER ] && status="on" || status="off"

		MIXLIST+="$NUMMIXER \"$card\" $status "
		let NUMMIXER+=1
	done < $MIXERS

	sh -c "/usr/bin/dialog $DIALOGOPTS --radiolist \"${TITCOL}Output Panel\" \
		$rows $cols $rows $MIXLIST 2> $TMP"

	[ $? -ne 0 ] && return

	let MIXER=$(cat $TMP)

	if [ -z "$(grep MIXER $SOMAOPTIONS)" ]; then
		echo -e "\n# Mixer Device" >> $SOMAOPTIONS
		echo "MIXER=$MIXER" >> $SOMAOPTIONS
	fi

	sed -i "s/MIXER=$tmp/MIXER=$MIXER/" $SOMAOPTIONS

	[ $MIXER -eq $tmp ] && return
}

# }}}
# {{{ Mixer
mixerpanel() {
	alsamixer -c $MIXER
}
# }}}
# {{{ Sched Main
schedule_main()
{
	touch $SCHEDULES

	while (true)
	do
		dialog --cancel-label Back $DIALOGOPTS --menu "${TITCOL}Scheduler" \
			$rows $cols $rows \
			View "View Schedule" \
			Add "Add Schedule" \
			Remove "Remove a Schedule" \
			2> $TMP

		[ $? -eq 1 ] && break

		choice=$(cat $TMP)
		case $choice in
		View)
			schedule_view
		;;
		Add)
			schedule_add
		;;
		Remove)
			schedule_remove
		;;
		*)
		;;
		esac
	done
}
# }}}
# {{{ View Sched
schedule_view()
{
	rm -f $TMP

	while read line
	do
		# Make it ape-readable
		date=$(echo $line | cut -d, -f1)
		year=${date:0:4}
		month=${date:4:2}
		day=${date:6:2}
		time=$(echo $line | cut -d, -f2)
		channel=$(echo $line | cut -d, -f3)

		echo "\Zn$day/$month/$year $time ${TITCOL}$channel" >> $TMP
	done < $SCHEDULES

	if [ -r $TMP ]; then
		dialog $DIALOGOPTS --title "${TITCOL}Set Schedules" \
			--msgbox "$(cat $TMP)" $rows $cols
	fi
}
# }}}
# {{{ Add Sched
schedule_add()
{
	cursor on

	get_schedule_time

	[ -z "$sched_time" ] && return

	get_schedule_recur

	[ "$sched_recur" == "0" ] && return

	if [ "$sched_recur" == "O" ]; then
		get_schedule_date
		if [ -z "$sched_date" ]; then
			return
		fi
	elif [ "$sched_recur" == "W" ]; then
		get_schedule_days
		[ -z "$sched_days" ] && return

	else
		sched_date="********"
		day="**"
		month="**"
		year="****"
	fi

	get_schedule_station

	[ -z "$sched_station" ] && return

	clear

	if [ "$sched_recur" == "W" ]; then
		for i in $sched_days
		do
			j=${i:0:2}
			sched_date="******$j"
			month="**"
			year="****"
			sed -i "/[*,$sched_date],$sched_time/d" $SCHEDULES
		done
	else
		sed -i "/[*,$sched_date],$sched_time/d" $SCHEDULES
	fi

	if [ "$day" == "**" ]; then
		sed -i "/$sched_time/d" $SCHEDULES
	fi

	if [ "$sched_recur" == "W" ]; then
		for i in $sched_days
		do
			j=${i:0:2}
			sched_date="******$j"
			month="**"
			year="****"
			day=".."
	echo "$sched_date,$sched_time,$sched_station" >> $SCHEDULES
		done
	else
		echo "$sched_date,$sched_time,$sched_station" >> $SCHEDULES
	fi

	sched_msg="${TITCOL}Schedule set:\Zn\n\n$day/$month/$year (DD/MM/YYYY)"
	sched_msg=$sched_msg"\n$sched_time\n$sched_station\n"

	if [ "$sched_recur" == "D" ]; then
		sched_msg=$sched_msg"Daily"
	elif [ "$sched_recur" == "W" ]; then
		sched_msg="${sched_msg}Every $sched_days"
	else
		sched_msg=$sched_msg"Once"
	fi

	dialog $DIALOGOPTS --title "Schedule" --msgbox \
		"$sched_msg" \
		11 40

	cursor off
}
# }}}
# {{{ Remove Sched
schedule_remove()
{
	while (true)
	do
		unset sched
		while read line
		do
			# More ape-like readable stuff
			date=$(echo $line | cut -d, -f1)
			year=${date:0:4}
			month=${date:4:2}
			day=${date:6:2}
			time=$(echo $line | cut -d, -f2)
			channel=$(echo $line | cut -d, -f3)
			# Since dialog defaults to the euro way of date format
			# I'll do it this way.
			sched="$sched \"$day\\$month\\$year $time\" \"$channel\""
		done < $SCHEDULES

		[ -z "$sched" ] && break

		sh -c "dialog $DIALOGOPTS --ok-label Delete --cancel-label Done \
			--title \"${TITCOL}Schedules\" --menu \"${TITCOL}Remove a Schedule\" \
			$rows $cols $rows $sched \
			2> $TMP"

		[ $? -eq 1 ] && return

		# Now make it machine readable (ish)
		if [ -n "$(cat $TMP)" ]; then
			torem="$(cat $TMP | sed 's# #,#')"
			year=${torem:6:4}
			month=${torem:3:2}
			day=${torem:0:2}

			[ "$year" == "****" ] && year="\*\*\*\*"
			[ "$month" == "**" ] && month="\*\*"
			[ "$day" == "**" ] && day="\*\*"

			time=${torem:11:5}

			if [ "$day" == "**" ]; then
				sed -i "/$time/d" $SCHEDULES
			else
				torem="$year$month$day,$time"
				sed -i "/$torem/d" $SCHEDULES
			fi
		else
			break
		fi
	done
}
# }}}
# {{{ Sched station changer
schedule_change_station()
{
	STATIONURL=$(grep "$SCHEDCHAN" $STATIONS | head -n 1 | cut -d, -f2)
	SCHEDRECUR=$(grep "*,$TIME" $SCHEDULES)

	[ "$SCHEDCHAN" == "$OLDCHANNEL" ] && [ "$CHANNEL" != "Idle" ] && return

	touch $STATUS

	[ -n "$(cat $STATUS)" ] && echo >> $STATUS
	[ -z "$SCHEDRECUR" ] && sed -i "/$DATE,$TIME/d" $SCHEDULES

	CHANNEL="$SCHEDCHAN"
	play
	setup
	laststation="$STATIONURL"
}
# }}}
#{{{ Sched Time
get_schedule_time()
{
	unset sched_time

	while [ ${#sched_time} -ne 5 ]
	do
		dialog $DIALOGOPTS --title "${TITCOL}Schedule Time" \
			--inputbox "Type in a time in 24 hour format (HH:MM)" 10 25 \
			2>$TMP

		[ $? -ne 0 ] && return
		sched_time=$(cat $TMP)
	done
}
# }}}
# {{{ Sched Station
get_schedule_station()
{
	let rows=$(stty size | cut -f1 -d' ')
	let cols=$(stty size | cut -f2 -d' ')

	# sh -c properly sends the quoted strings to dialog
	sh -c "dialog $DIALOGOPTS --menu \"${TITCOL}Stations\" $rows $cols $rows \
		$STATIONLIST" 2> $TMP

	[ $? -ne 0 ] && return

	sched_station="$(cat $TMP)"
}
# }}}
# {{{ Sched Recurring?
get_schedule_recur()
{
	dialog $DIALOGOPTS --menu "${TITCOL}Recurrance" \
		10 30 3 \
			"Once" "Once Only" \
			"Daily" "Daily Schedule" \
			"Weekly" "Weekly Schedule" \
			2>$TMP

	if [ $? -eq 0 ]; then
		if [ "$(cat $TMP)" = "Once" ]; then
			sched_recur="O"
		elif [ "$(cat $TMP)" = "Daily" ]; then
			sched_recur="D"
		elif [ "$(cat $TMP)" = "Weekly" ]; then
			sched_recur="W"
		fi
	elif [ $? -eq 1 ]; then
		sched_recur="0"
		return
	fi
}
# }}}
# {{{ Sched Days
get_schedule_days()
{
	dialog $DIALOGOPTS --separate-output --checklist "${TITCOL}Select A Day" \
		14 25 8 \
			Monday " " off \
			Tuesday " " off \
			Wednesday " " off \
			Thursday " " off \
			Friday " " off \
			Saturday " " off \
			Sunday " " off \
			2>$TMP

	[ $? -eq 0 ] && sched_days=$(cat $TMP) || sched_days="" && return
}
# }}}
# {{{ Sched Date
get_schedule_date()
{
	unset sched_date

	dialog $DIALOGOPTS --title "${TITCOL}Schedule Date" \
		--calendar "\nUse tab to traverse windows\n" 5 50 2>$TMP

	date=$(cat $TMP)

	[ -z "$date" ] && return

	year="$(echo $date | cut -d/ -f3)"
	month="$(echo $date | cut -d/ -f2)"
	day="$(echo $date | cut -d/ -f1)"
	sched_date="$year$month$day"
}
# }}}
# {{{ Edit options
edit_options()
{
	while true
	do
		let rows=$(stty size | cut -f1 -d' ')
		let cols=$(stty size | cut -f2 -d' ')

		dialog --cancel-label "Back" $DIALOGOPTS --menu "${TITCOL}Options" \
			$rows $cols $rows \
			"THEME" "Choose a theme" \
			"DIALOGOPTS" "Dialog Options" \
			"OUTCARD" "Output Device" \
			"AFFILTER" "MPlayer affilter" \
			"SOFTVOL" "MPlayer Software Volume" \
			"CACHE" "MPlayer Cache" \
			"SAVE_LIST_AT_QUIT" "Save List" \
			"MIXER" "Mixer Device" \
			"TITCOL" "Dialog Title Colour" \
			"CONNECTTIMEOUT" "Connection Timeout" \
			2> $TMP

		[ $? -ne 0 ] && return

		option=$(cat $TMP)

		cursor on

		[ "$option" == "THEME" ] && theme
		[ "$option" == "DIALOGOPTS" ] && dialogopts
		[ "$option" == "OUTCARD" ] && outcard
		[ "$option" == "AFFILTER" ] && affilter
		[ "$option" == "SOFTVOL" ] && softvol
		[ "$option" == "CACHE" ] && cache
		[ "$option" == "SAVE_LIST_AT_QUIT" ] && save_list_at_quit
		[ "$option" == "MIXER" ] && edit_mixer
		[ "$option" == "TITCOL" ] && titcol
		[ "$option" == "CONNECTTIMEOUT" ] && timeout

		cursor off
	done
}
# }}}
# {{{ Edit DIALOGOPTS
dialogopts()
{
	CUR=$(egrep ^DIALOGOPTS= $SOMAOPTIONS | cut -d= -f2 | sed 's/"//g;s#^-# -#g')
	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Edit dialog options" \
		--inputbox "Edit dialog options.\n\nNote that removing '--colors' only affects the title bar in the dialog command. It doesn't affect the theme colours.\nDefault: --colors\n " \
		$rows $cols -- "$(egrep ^DIALOGOPTS= $SOMAOPTIONS | cut -d= -f2 | sed 's/"//g')" \
		2> $TMP

	retval=$?

	[ -z "$(cat $TMP)" ] && [ $retval -ne 0 ] && return
	NEW="\"$(cat $TMP)\""
	sed -i -- 's#^DIALOGOPTS=.*#DIALOGOPTS='$NEW'#' $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Edit theme
theme()
{
	CUR=$(grep "export DIALOGRC=" $SOMAOPTIONS | cut -d= -f2)
	LIST=$(ls -1 ~/.soma/themes/ | \
		sed 's#^#~/.soma/themes/#;s#$# Select #g')

	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Choose a theme." \
		--menu "Edit your dialog theme.  Current theme: $CUR\nOnly those stored in ~/.soma/themes are listed." \
		$rows $cols $rows \
		$LIST \
		"/dev/null" "Select" \
		2> $TMP

	[ -z "$(cat $TMP)" ] && return
	sed -i "s#^export DIALOGRC=.*#export DIALOGRC=$(cat $TMP)#" $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Edit OUTCARD
outcard()
{
	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Edit output device" \
		--inputbox "Edit your output device.\n " \
		$rows $cols "$(egrep ^OUTCARD= $SOMAOPTIONS | cut -d= -f2 | sed 's/"//g')" \
		2> $TMP

	[ -z "$(cat $TMP)" ] && return
	sed -i "s#^OUTCARD=.*#OUTCARD=\"$(cat $TMP)\"#" $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Edit AFFILTER
affilter()
{
	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Edit affilter" \
		--inputbox "Edit MPlayer affilter.\n " \
		$rows $cols -- "$(egrep ^AFFILTER= $SOMAOPTIONS | cut -d= -f2- | sed 's/"//g')" \
		2> $TMP

	retval=$?

	[ -z "$(cat $TMP)" ] && [ $retval -ne 0 ] && return
	sed -i "s#^AFFILTER=.*#AFFILTER=\"$(cat $TMP)\"#" $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Edit SOFTVOL
softvol()
{
	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Edit softvol" \
		--inputbox "Edit MPlayer softvol.\n\nDefault: -softvol\n " \
		$rows $cols -- "$(egrep ^SOFTVOL= $SOMAOPTIONS | cut -d= -f2 | sed 's/"//g')" \
		2> $TMP

	retval=$?

	[ -z "$(cat $TMP)" ] && [ $retval -ne 0 ] && return
	sed -i "s#^SOFTVOL=.*#SOFTVOL=\"$(cat $TMP)\"#" $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Edit CACHE
cache()
{
	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Edit cache" \
		--inputbox "Edit MPlayer cache.\n\nDefault: 320\n " \
		$rows $cols "$(egrep ^CACHE= $SOMAOPTIONS | cut -d= -f2 | sed 's/"//g')" \
		2> $TMP

	[ -z "$(cat $TMP)" ] && return
	sed -i "s#^CACHE=.*#CACHE=$(cat $TMP)#" $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Save list at quit
save_list_at_quit()
{
	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Save list at quit " \
		--inputbox "Save list at quit.\n\nAllowed values: 1 or 0\n\nDefault: 0\n " \
		$rows $cols "$(egrep ^SAVE_LIST_AT_QUIT= $SOMAOPTIONS | cut -d= -f2 | sed 's/"//g')" \
		2> $TMP

	[ -z "$(cat $TMP)" ] && return
	sed -i "s#^SAVE_LIST_AT_QUIT=.*#SAVE_LIST_AT_QUIT=$(cat $TMP)#" $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Edit MIXER
edit_mixer()
{
	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Edit mixer device" \
		--inputbox "Edit mixer device\n\n " \
		$rows $cols "$(egrep ^MIXER= $SOMAOPTIONS | cut -d= -f2 | sed 's/"//g')" \
		2> $TMP

	[ -z "$(cat $TMP)" ] && return
	sed -i "s#^MIXER=.*#MIXER=$(cat $TMP)#" $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Edit TITCOL
titcol()
{
	DEF='\\ZZZb'
	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Edit dialog title setting" \
		--inputbox "Edit dialog title setting\nDefault: $DEF\n " \
		$rows $cols "$(egrep ^TITCOL= $SOMAOPTIONS | cut -d= -f2 | sed 's/"//g')" \
		2> $TMP

	[ -z "$(cat $TMP)" ] && return

	retval=$?

	[ -z "$(cat $TMP)" ] && [ $retval -ne 0 ] && return
	Z="\"$(cat $TMP | sed 's%\\%\\\\%g')\""
	sed -i 's%^TITCOL=.*%TITCOL='$Z'%' $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Edit CONNECTTIMEOUT
timeout()
{
	dialog --cancel-label Back $DIALOGOPTS --title "${TITCOL}Edit connection timeout" \
		--inputbox "Edit connection timeout setting\nDefault: 150\n " \
		$rows $cols "$(egrep ^CONNECTTIMEOUT= $SOMAOPTIONS | cut -d= -f2 | sed 's/"//g')" \
		2> $TMP

	[ -z "$(cat $TMP)" ] && return
	sed -i "s#^CONNECTTIMEOUT=.*#CONNECTTIMEOUT=$(cat $TMP)#" $SOMAOPTIONS
	source $SOMAOPTIONS
}
# }}}
# {{{ Begin
if [ "$UID" = "0" ]; then
	echo "Do NOT run this program as root!"
	exit
fi

VERSION="2.12.3"
get_commandline "$@"
init
mainmenu

# }}}

# vim: tw=0
