#!/bin/sh
# {{{ Copyright
# Soma - a command line/dialog radio player
#
# Copyright 2010-2011  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 Pat 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
    VERSION="2.10.4"
    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
    PIDFILE=$SOMAROOT/mplayer.pid
    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/dialogrc

    if [ -r $PIDFILE ]; then kill $(cat $PIDFILE) 2> /dev/null; fi
    rm -f $MIXER $STATIONS $MSTATUS $STATUS $PIDFILE $TMP
    if [ ! -d ~/.soma ]; then mkdir ~/.soma; fi
    if [ ! -r $SOMAOPTIONS ]; then cat /etc/soma/options.conf > $SOMAOPTIONS; fi
    if [ ! -r $DIALOGRC ]; then
        cat /etc/soma/dialogrc > $DIALOGRC
        cat /etc/soma/greenrc > ~/.soma/greenrc
    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]="jack"
    DEVICE[1]="nas"

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

    if [ -r $USRSTATIONS ]; then
        cat $USRSTATIONS | sed 's/, /,/g;s/ $//g' > $STATIONS
    fi

    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
        if [ "$1" = "-h" ]; then usage; exit; fi
        if [ "$1" = "-v" ]; then version; fi
        if [ "$1" = "-d" ]; then DEBUG="1"; fi
        shift
    done
}
# }}}
# {{{ Version
version() {
    echo "Soma $VERSION"
    exit
}
# }}}
# {{{ Usage

usage() {
cat << EOF
Soma $VERSION © 2010 David Woodfall

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	    Some options you can edit - TERM etc.
~/.soma/stations.conf	    User radio station list.
~/.soma/dialogrc-$VERSION  	    Colours for dialog.
~/.soma/schedules	    Saved schedules

EOF
return
}
# }}}
# {{{ Cleanup/exit
cleanup() {
    clear
    kill $(cat $PIDFILE 2>/dev/null) 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 "\Zb\Z7Soma $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 "\Zb\Z7Soma $VERSION" \
                $rows $cols $rows Station "Choose a Station" Mixer Mixer \
                Status "Playing Now" "Output" "Choose Sound 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)"

        if [ "$main" == "Mixer" ]; then mixerpanel; fi
        if [ "$main" == "Station" ]; then stationselector; fi
        if [ "$main" == "Status" ]; then status; fi
        if [ "$main" == "Scheduler" ]; then schedule_main; fi
        if [ "$main" == "Output" ]; then selectoutput; fi
        if [ "$main" == "Choose Mixer" ]; then selectmixer; fi
        if [ "$main" == "Save" ]; then save; fi
        if [ "$main" == "Quit" ]; then cleanup; fi
        if [ "$main" == "Debug" ]; then rawstatus; fi
    done
}
# }}}
# {{{ Play
play()
{
    source $SOMAOPTIONS
    if [ -n "$MPLAYERPID" ]; then
        kill $(cat $PIDFILE) 2>/dev/null
    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 file

    if [ -n "$(echo $STATIONURL | grep .pls)" ]; then file="pls"; fi
    if [ -n "$(echo $STATIONURL | grep .m3u)" ]; then file="m3u"; fi
    if [ -n "$(echo $STATIONURL | grep .ram)" ]; then file="ram"; fi
    if [ -n "$(echo $STATIONURL | grep .asx)" ]; then file="asx"; fi
    if [ -n "$(echo $STATIONURL | grep .wvx)" ]; then file="wvx"; fi
    
    if [ -n "$file" ];then
        PLAYLIST="-playlist"
    else
        unset PLAYLIST
    fi

    if [ -n "$SETVOL" ]; then
        VOL="-volume $SETVOL"
    fi

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

    MPLAYERPID=$!
    echo $MPLAYERPID >> $PIDFILE
                                                  
    dialog $DIALOGOPTS --title "\Zb\Z7Status\Z7" --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 "\Zb\Z7Status" --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 "\Zb\Z7Status" --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

    if [ -z "$TITLE" ]; then
        TITLE="$CHANNEL"
    fi

    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() {
    let rows=$(stty size | cut -f1 -d' ')
    let cols=$(stty size | cut -f2 -d' ')

    if [ -z "$MPLAYERPID" ]; then
        CHANNEL="Idle"
        unset TITLE
        unset lasttitle
        touch $STATUS
        touch $MSTATUS
    fi

    dialog $DIALOGOPTS --exit-label "Back" --keep-window --timeout 1 \
        --title "\Zb\Z7[$TIME] $CHANNEL" --tailbox $STATUS $rows $cols 2> $TMP
    exitwound="$?"
    if [ "$exitwound" = "0" ]; then
        mainmenu
    fi
    if
        [ "$exitwound" = "255" ] && [ -z "$(cat $TMP)" ]; then
        mainmenu
    fi

    while (true)
    do
        # it sometimes comes back so put it here too
        setterm -cursor off
        let rows=$(stty size | cut -f1 -d' ')
        let cols=$(stty size | cut -f2 -d' ')

        if [ -n "$MPLAYERPID" ]; then
            title
        fi
        
        lasttime=$TIME
        TIME=$(date +"%H:%M")
        DATE=$(date +"%Y%m%d")
        FULLDAY=$(date +"%a")
        DAY=${FULLDAY:0:2}
        DATE2="$(date +"%Y%m")$DAY"

        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 "$TITLE" | cut -d':' -f2 > $PLAYING
                echo "$CHANNEL:$TITLE" >  $PLAYING
            fi

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

            if [ "$exitwound" = "0" ]; then
                mainmenu
            fi
            if
                [ "$exitwound" = "255" ] && [ -z "$(cat $TMP)" ]; then
                mainmenu
            fi
        fi
        input
        lasttitle="$TITLE"
    done
}
# }}}
# {{{ Input
input() {
    unset REPLY
    read -sn1 -t1
    
    if [ "$?" != "0" ]; then
        return
    fi

    case $REPLY in
        ' ')
            echo "pause"  > $FIFO
            if [ "$CHANNEL" = "Paused" ]; then
                CHANNEL=$OLDCHANNEL
            else
                CHANNEL="Paused"
            fi
            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
        ;;
        '(')
        if [ "$SOFTVOL" = "-softvol" ]; then
            echo "volume -50"  > $FIFO
        fi
            ;;
        ')')
        if [ "$SOFTVOL" = "-softvol" ]; then
            echo "volume +50"  > $FIFO
        fi
            ;;
        '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
            ;;
        *)
            ;;
    esac
}
# }}}
# {{{ Halp!
help()
{
    clear    
    usage
    echo "Any key to return"
    read -sn1
}
# }}}
# {{{ Raw status
rawstatus() {
    let rows=$(stty size | cut -f1 -d' ')
    let cols=$(stty size | cut -f2 -d' ')
    if [ -z "$MPLAYERPID" ]; then 
        dialog $DIALOGOPTS --title "\Zb\Z7Status" --msgbox "No stream!" $rows $cols
        return
    fi

    dialog $DIALOGOPTS --exit-label "Back" --keep-window \
        --title "\Zb\Z7$CHANNEL" --tailbox $MSTATUS $rows $cols 2> $TMP
    exitwound="$?"
    if [ "$exitwound" = "0" ]; then return; fi
    if [ "$exitwound" = "255" ] && [ -z "$(cat $TMP)" ]; then return; fi
}

# }}}
# {{{ 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 \"\Zb\Z7Stations\" $rows $cols \
        $rows $STATIONLIST 2>$TMP"
    retval="$?"
    if [ "$retval" = "255" ] || [ "$retval" = "1" ]; then return; fi

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

    CHANNEL="$(cat $TMP)"

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

    if [ "$STATIONURL" = "$laststation" ]; then status; fi

    touch $STATUS

    if [ -n "$(cat $STATUS)" ]; then
        echo >> $STATUS
    fi

    play
    setup

    laststation=$STATIONURL
    if [ -n "$DEBUG" ]; then 
        rawstatus
    else
        status
    fi
}

# }}}
# {{{ 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"

    if [ "$tmp" == "alsa" ]; then
        status="on"
    else
        status="off"
    fi

    CARDLIST="0 \"Alsa default softmix.\" $status "

    for i in $(seq $NUMDEVICES)
    do
        if [ "$OUTCARD" = "alsa:${DEVICE[i]}" ]; then
            status="on"
        else
            status="off"
        fi
        CARDLIST+="$i \"alsa:${HWDEVICE[i]}\" $status "
    done

    if [ "$tmp" == "jack" ]; then
        status="on"
    else
        status="off"
    fi
    CARDLIST="$CARDLIST $((i+1)) \"Jack.\" $status "
    
    if [ "$tmp" == "nas" ]; then
        status="on"
    else
        status="off"
    fi
    CARDLIST="$CARDLIST $((i+2)) \"NAS.\" $status "

    sh -c "/usr/bin/dialog $DIALOGOPTS --radiolist \"\Zb\Z7Output Panel\" \
        $rows $cols $rows $CARDLIST 2> $TMP"

    retval="$?"
    if [ "$retval" = "255" ] || [ "$retval" = "1" ]; then return; fi

    let RESULT=$(cat $TMP)

    if [ $RESULT -eq 0 ]; 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
    fi

    sed -i "s/OUTCARD=\"$tmp\"/OUTCARD=\"$OUTCARD\"/" $SOMAOPTIONS

    CARDINDEX="$(echo $OUTCARD | cut -d= -f3 | cut -d, -f1)"
    if [ "$OUTCARD" == "$tmp" ]; then return; fi
    if [ -z "$TITLE" ]; then return; fi
    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
    tmp=$MIXER
    status="off"
    
    aplay -l | grep card | cut -d, -f1 | sort -u > $MIXERS
    
    while read card
    do
        if [ "$tmp" = "$NUMMIXER" ]; then
            status="on"
        else
            status="off"
        fi

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

    sh -c "/usr/bin/dialog $DIALOGOPTS --radiolist \"\Zb\Z7Output Panel\" \
        $rows $cols $rows $MIXLIST 2> $TMP"

    retval="$?"
    if [ "$retval" = "255" ] || [ "$retval" = "1" ]; then return; fi

    let RESULT=$(cat $TMP)

    MIXER="$RESULT"

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

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

    MIXINDEX="$(echo $MIXER | cut -d= -f3 | cut -d, -f1)"
    if [ "$MIXER" == "$tmp" ]; then return; fi
    if [ -z "$TITLE" ]; then return; fi
    status
}

# }}}
# {{{ Mixer
mixerpanel() {
    alsamixer -c $MIXER
}
# }}}
# {{{ Sched Main
schedule_main()
{
    touch $SCHEDULES
    while (true)
    do
        dialog --cancel-label Back $DIALOGOPTS --menu "\Zb\Z7Scheduler" \
            $rows $cols $rows \
            View "View Schedule" \
            Add "Add Schedule" \
            Remove "Remove a Schedule" \
            2> $TMP
        exitwound="$?"
        if [ "$exitwound" = "1" ]; then
            break
        fi

        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 \Zb\Z7$channel" >> $TMP
    done < $SCHEDULES

    if [ -r $TMP ]; then
        dialog $DIALOGOPTS --title "\Zb\Z7Set Schedules" \
            --msgbox "$(cat $TMP)" $rows $cols
    fi
}
# }}}
# {{{ Add Sched 
schedule_add()
{
    setterm -cursor on
    
    get_schedule_time
    if [ -z "$sched_time" ]; then
        return
    fi

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

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

    get_schedule_station
    if [ -z "$sched_station" ]; then
        return
    fi

    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="\Zb\Z7Schedule 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
        
        if [ -z "$sched" ]; then
            break
        fi
        sh -c "dialog $DIALOGOPTS --ok-label Delete --cancel-label Done \
            --title \"\Zb\Z7Schedules\" --menu \"\Zb\Z7Remove a Schedule\" \
            $rows $cols $rows $sched \
            2> $TMP"
        exitwound="$?"

        if [ "$exitwound" = "1" ]; then
            return
        fi

        # 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}
            if [ "$year" = "****" ]; then
                year="\*\*\*\*"
            fi
            if [ "$month" = "**" ]; then
                month="\*\*"
            fi
            if [ "$day" = "**" ]; then
                day="\*\*"
            fi
            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)

    if [ "$SCHEDCHAN" = "$OLDCHANNEL" ] && [ "$CHANNEL" != "Idle" ]; then return; fi

    touch $STATUS

    if [ -n "$(cat $STATUS)" ]; then
        echo >> $STATUS
    fi

    if [ -z "$SCHEDRECUR" ]; then
        sed -i "/$DATE,$TIME/d" $SCHEDULES
    fi

    CHANNEL=$SCHEDCHAN
    play
    setup
    laststation=$STATIONURL
}
# }}}
#{{{ Sched Time
get_schedule_time()
{
    unset sched_time
    while [ ${#sched_time} -ne 5 ]
    do
        dialog $DIALOGOPTS --title "\Zb\Z7Schedule Time" \
            --inputbox "Type in a time in 24 hour format (HH:MM)" 10 25 \
            2>$TMP
        retval="$?"
        if [ "$retval" = "255" ] || [ "$retval" = "1" ]; then return; fi
        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 \"\Zb\Z7Choose Station\" $rows $cols \
        $rows $STATIONLIST 2>$TMP"
    retval="$?"
    if [ "$retval" = "255" ] || [ "$retval" = "1" ]; then return; fi

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

    if [ "$?" = "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 [ "$?" = "1" ]; then
        sched_recur="0"
        return
    fi
}
# }}}
# {{{ Sched Days
get_schedule_days()
{
    dialog $DIALOGOPTS --separate-output --checklist "\Zb\Z7Select A Day" \
        14 25 8 \
            Monday " " off \
            Tuesday " " off \
            Wednesday " " off \
            Thursday " " off \
            Friday " " off \
            Saturday " " off \
            Sunday " " off \
            2>$TMP
    if [ "$?" = "0" ]; then 
        sched_days=$(cat $TMP)
    else 
        sched_days=""
        return
    fi
}
# }}}
# {{{ Sched Date
get_schedule_date()
{
    unset sched_date
    dialog $DIALOGOPTS --title "\Zb\Z7Schedule Date" \
        --calendar "\nUse tab to traverse windows\n" 5 50 2>$TMP
    date=$(cat $TMP)
    if [ -z "$date" ]; then
        return
    fi
    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

get_commandline "$@"
init
mainmenu
# }}}
