#!/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.

# }}}
# {{{ Init
init() {
    trap "cleanup" HUP INT ABRT QUIT SEGV TERM KILL PIPE STOP TSTP
    tput smcup
    setterm -cursor off
    clear
    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 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
    source /etc/soma/options.conf
    source $SOMAOPTIONS
    touch $SCHEDULES

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

    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"

    [ -r $USRSTATIONS ] && cat $USRSTATIONS \
        | grep ',' | sed 's#, #,#g;s# $##g' > $STATIONS

    cat $DEFSTATIONS >> $STATIONS

    while read i
    do
        title[$c]=$(echo $i | cut -d, -f1)
        url[$c]=$(echo $i | cut -d, -f2)
        STATIONLIST+="\"${title[c]}\" \"${url[c]}\" "
        let c=$c+1
    done < $STATIONS
    clear
}
# }}}
# {{{ Command line
get_commandline() {
    until [ -z "$1" ]
    do
        [ "$1" == "-h" ] && usage && exit
        [ "$1" == "-v" ] && 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
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

    clear
    kill $MPLAYERPID 2>/dev/null
    rm -fr $SOMAROOT
    tput rmcup
    setterm -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() {
    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}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" \
                Quit "Quit Soma" \
                2> $TMP
            retval="$?"
            if [ "$retval" = "255" ] || [ "$retval" = "1" ]; then cleanup; fi
        else
            dialog --cancel-label Quit $DIALOGOPTS --menu "${TITCOL}Soma $VERSION" \
                $rows $cols $rows \
                Station "Choose a Station" \
                Status "Playing Now" \
                Mixer Mixer \
                Output "Choose Sound Device" \
                "Choose Mixer" "Choose Mixer Device" \
                Save "Save Track List"\
                Debug "Raw MPlayer Output" \
                Quit "Quit Soma" \
                2> $TMP
            retval="$?"
            if [ "$retval" = "255" ] || [ "$retval" = "1" ]; then cleanup; fi
        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" == "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" -ge 150 ]; then
            dialog $DIALOGOPTS --title "${TITCOL}Status" --ok-label "Main Menu" \
                --msgbox "No stream!" $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=$(grep $STATIONURL $STATIONS 2>/dev/null | head -n 1 | \
            cut -d, -f1 | 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() {
    setterm -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" --ok-label "Main Menu" \
                    --msgbox "No stream!" $rows $cols

                lasttitle="Idle"
                TITLE="Idle"
                unset laststation
                unset MPLAYERPID
                CHANNEL="Idle"
                mainmenu
            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
        ;;
        *)
        ;;
    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

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

    retval=$?

    [ $retval -eq 255 ] || [ $retval -eq 1 ] && return

    STATIONURL=$(grep "$(cat $TMP)," $STATIONS | cut -d, -f2 | head -n 1)
    CHANNEL="$(cat $TMP)"

    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"

    retval=$?

    [ $retval -eq 255 ] || [ $retval -eq 1 ] && 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"

    [ $? -eq 255 ] || [ $? -eq 1 ] && 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()
{
    setterm -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
    setterm -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

        [ $? -eq 255 ] || [ $? -eq 1 ] && 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' ')

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

    [ $? -eq 255 ] || [ $? -eq 1 ] && 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"
}
# }}}
# {{{ Begin
if [ "$UID" = "0" ]; then
    echo "Do NOT run this program as root!"
    exit
fi

VERSION="2.11.3"
get_commandline "$@"
init
mainmenu
# }}}

# vim: tw=0
