#!/bin/bash
#
# MusicBox Sound configuration script
#

CONFIG_FILE=/boot/config/settings.ini
BOOT_CONFIG_TXT=/boot/config.txt
TMP_CONFIG_TXT=/tmp/config.txt
ETC_ASOUND_CONF=/etc/asound.conf
CARD_LIST_FILE=/tmp/aplay.list

echo "Setting sound configuration..."
# Prepare to remove whatever is currently there.
rm -f $ETC_ASOUND_CONF
sed '/# Musicbox audio:/Q' $BOOT_CONFIG_TXT > $TMP_CONFIG_TXT

I2S_CARD=
USB_CARD=
INT_CARD=
HDMI_CARD=
LOCAL_REBOOT=0

function get_overlay()
{
    local overlay=$1
    case $overlay in
        audioinjector-pi-soundcard)
            overlay="audioinjector-wm8731-audio"
            ;;
        audioinjector-octo-soundcard)
            overlay="audioinjector-addons"
            ;;
        iqaudio-dac)
            overlay="iqaudio-dacplus,unmute_amp"
            ;;
        allo-boss-dac)
            overlay="allo-boss-dac-pcm512x-audio"
            ;;
        allo-piano-dac)
            overlay="allo-piano-dac-pcm512x-audio"
            ;;
        allo-piano-dac-plus)
            overlay="allo-piano-dac-plus-pcm512x-audio"
            ;;
        *)
            ;;
    esac
    eval "$2='$overlay'"
}

function enumerate_alsa_cards()
{
    local i2s_NAME=$(echo $1 | tr -d "[:punct:]")
    echo "Probing sound devices:"
    aplay -l | grep card | tee $CARD_LIST_FILE
    while read -r line
    do
        ## HifiBerry DAC
        #card 0: sndrpihifiberry [snd_rpi_hifiberry_dac], device 0: HifiBerry DAC HiFi pcm5102a-hifi-0 []
        ## HifiBerry Digi (hifiberry-digi)
        #card 2: sndrpihifiber_1 [snd_rpi_hifiberry_digi], device 0: HifiBerry Digi HiFi wm8804-spdif-0 []
        ## HiFiBerry DAC+
        #card 1: sndrpihifiber_1 [snd_rpi_hifiberry_dacplus], device 0: HiFiBerry DAC+ HiFi pcm512x-hifi-0 []
        # IQaudIO
        #card 1: sndrpiiqaudioda [snd_rpi_iqaudio_dac], device 0: IQaudIO DAC HiFi pcm512x-hifi-0 []
        #card 1: IQaudIODAC [IQaudIODAC], device 0: IQaudIO DAC HiFi pcm512x-hifi-0 []
        ## Wolfson
        #Card 0: sndrpiwsp [snd_rpi_wsp], device 0: WM5102 AiFi wm5102-aif1-0 []
        ## AudioInjector stereo and octo
        #card 0: audioinjectorpi [audioinjector-pi-soundcard], device 0: AudioInjector audio wm8731-hifi-0 []
        #card 0: audioinjectoroc [audioinjector-octo-soundcard], device 0: AudioInject-HIFI cs42448-0 []
        ## Allo Boss DAC (allo-boss-dac-pcm512x-audio)
        #card 0: BossDAC [BossDAC], device 0: BossDAC pcm512x-hifi-0 []
        ## Allo Piano DAC (allo-piano-dac-pcm512x-audio)
        #card 0: PianoDAC [PianoDAC], device 0: Piano DAC HiFi pcm512x-hifi-0 []
        ## JustBoom DAC
        #card 0: sndrpijustboomd [snd_rpi_justboom_dac], device 0: JustBoom DAC HiFi pcm512x-hifi-0 []
        ## Onboard
        #card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
        #card 0: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]
        ## USB
        #card 2: AUDIO [USB  AUDIO], device 0: USB Audio [USB Audio]
        #card 2: DAC [USB Audio DAC], device 0: USB Audio [USB Audio]
        #card 2: CODEC [USB Audio CODEC], device 0: USB Audio [USB Audio]

        # Remove unwanted characters, make lowercase and split on whitespace.
        line=$(echo $line | tr "[:upper:]" "[:lower:]" | tr -d "[:punct:]")
        dev=($(echo $line))
        card_num=${dev[1]}
        name=${dev[3]}
        if [[ $name == "bcm2835" ]]; then
            INT_CARD=$card_num
            echo "* Found internal device: card$INT_CARD"
            if tvservice -n 2>&1 | grep -v -q "No device present"; then
                echo "    HDMI output detected"
                HDMI_CARD=$card_num
            fi
        elif [[ $i2s_NAME && $name == *"$i2s_NAME" ]]; then
            I2S_CARD=$card_num
            echo "* Found i2s device: card$I2S_CARD"
        elif [[ $line =~ "usb audio" ]]; then
            USB_CARD=$card_num
            echo "* Found usb device: card$USB_CARD"
        else
            UNKNOWN_CARD=$card_num
            echo "* Found unknown device '$name' on card$UNKNOWN_CARD"
        fi
    done < <(cat $CARD_LIST_FILE)
    # No usb card found, assume anything unknown is actually a usb card.
    [[ -z $USB_CARD ]] && USB_CARD=$UNKNOWN_CARD
    # Check if we need to make any changes to config.txt
    if [ -n "$i2s_NAME" ]; then
        if [ -z "$I2S_CARD" ] ; then
            local dto_NAME=''
            get_overlay $1 dto_NAME
            if ! grep -q "^dtoverlay=${dto_NAME}$" $BOOT_CONFIG_TXT ; then
                echo "# Musicbox audio: (DO NOT EDIT BELOW THIS LINE)" >> $TMP_CONFIG_TXT
                echo "dtoverlay=${dto_NAME}" >> $TMP_CONFIG_TXT
                echo "Enabling Device Tree Overlay '$dto_NAME' and rebooting to activate..."
                LOCAL_REBOOT=1
                return
            else
                echo "******************************************************************************************"
                echo "ERROR: Device Tree Overlay '$dto_NAME' is already present"
                echo "       in $BOOT_CONFIG_TXT but unable to find soundcard."
                echo "******************************************************************************************"
            fi
        fi
        rm -f $TMP_CONFIG_TXT
    fi
}

if [[ $INI_READ != true ]] 
then
    echo "read ini"
    # Import ini parser
    . /opt/musicbox/read_ini.sh

    # Convert windows ini to unix
    dos2unix -n $CONFIG_FILE /tmp/settings.ini > /dev/null 2>&1 || true

    # ini vars to mopidy settings
    read_ini /tmp/settings.ini

    rm /tmp/settings.ini > /dev/null 2>&1 || true
fi

# If output not defined, it will automatically detect USB / HDMI / Analog in given order
# It is at this moment not possible to detect whether an i2s device is connected hence
# i2s is only selected if explicitly given as output in the config file
OUTPUT=$(echo $INI__musicbox__output | tr "[:upper:]" "[:lower:]" | tr "_" "-")
CARD=

if [[ -z "$OUTPUT" ]]
then
    OUTPUT="auto"
fi
# Get alsa cards
enumerate_alsa_cards

case $OUTPUT in
    auto)
        ;;
    analog|hdmi)
        CARD=$INT_CARD
        ;;
    usb)
        CARD=$USB_CARD
        ;;
    wolfson)
        enumerate_alsa_cards wsp
        CARD=$I2S_CARD
        ;;
    audioinjector-wm8731-audio)
        enumerate_alsa_cards audioinjector-pi-soundcard
        CARD=$I2S_CARD
        ;;
    audioinjector-addons)
        enumerate_alsa_cards audioinjector-octo-soundcard
        CARD=$I2S_CARD
        ;;
    iqaudio-dacplus)
        enumerate_alsa_cards iqaudio-dac
        CARD=$I2S_CARD
        ;;
    phatdac)
        echo "phatdac option is deprecated, use hifiberry_dac instead"
        enumerate_alsa_cards hifiberry-dac
        CARD=$I2S_CARD
        ;;
    *)
        enumerate_alsa_cards $OUTPUT
        CARD=$I2S_CARD
        ;;
esac

if [ -f $TMP_CONFIG_TXT ]; then
    mv $TMP_CONFIG_TXT $BOOT_CONFIG_TXT
fi

if [ "$LOCAL_REBOOT" == "1" ]
then
    REBOOT=1
    return
fi


echo "Selected card=$CARD  (i2s=$I2S_CARD  output=$OUTPUT  usb=$USB_CARD  intc=$INT_CARD)"
# If preferred output not found or given fall back to auto detection
if [[ -z $CARD ]];
then
    echo "No output was specified/found, falling back to auto detection"
    if [[ -n $USB_CARD ]]; then
        CARD=$USB_CARD
        OUTPUT="usb"
    else
        CARD=$INT_CARD
        if  [[ -n $HDMI_CARD ]]; then
            OUTPUT="hdmi"
        else
            OUTPUT="analog"
        fi
    fi
    echo "Selected card=$CARD  (i2s=$I2S_CARD  output=$OUTPUT  usb=$USB_CARD  intc=$INT_CARD)"
fi

if [[ -z $CARD ]];
then
    echo "****************************"
    echo "WARNING: No audio card found"
    echo "****************************"
    exit 1
else
    echo "Using audio card$CARD ($OUTPUT)"
fi

if [ "$OUTPUT" == "usb" -a "$INI__musicbox__downsample_usb" == "1" ]
# resamples to 44K because of problems with some usb-dacs on 48k (probably related to usb drawbacks of Pi)
# and extra buffer for usb
#if [ "$OUTPUT" == "usb" ]
then
cat << EOF > $ETC_ASOUND_CONF
pcm.!default {
    type plug
    slave.pcm {
        type dmix
        ipc_key 1024
        slave {
            pcm "hw:$CARD"
            rate 44100
#            period_time 0
#            period_size 4096
#            buffer_size 131072
        }
    }
}
ctl.!default {
    type hw
    card $CARD
}
EOF
else
cat << EOF > $ETC_ASOUND_CONF
pcm.!default {
    type hw
    card $CARD
}
ctl.!default {
    type hw
    card $CARD
}
EOF
fi

# Reset mixer
amixer cset numid=3 0 > /dev/null 2>&1 || true

if [ "$OUTPUT" == "analog" ]
then
    # Set mixer to analog output
    amixer cset numid=3 1 > /dev/null 2>&1 || true
elif [ "$OUTPUT" == "hdmi" ]
then
    # Set mixer to hdmi
    amixer cset numid=3 2 > /dev/null 2>&1 || true
fi

for CTL in \
        Master \
        PCM \
        Line \
        "PCM,1" \
        Wave \
        Music \
        AC97 \
        "Master Digital" \
        DAC \
        "DAC,0" \
        "DAC,1" \
        Speaker \
    Playback \
    Digital \
    Aux \
    Front \
    Center
do
    # Set initial hardware volume
    amixer set -c $CARD "$CTL" 96% unmute > /dev/null 2>&1 || true 
    #amixer set -c $CARD "$CTL" ${VOLUME}% unmute > /dev/null 2>&1 || true 
done

# Set PCM of Pi higher, because it's really quiet otherwise (hardware thing)
amixer -c 0 set PCM playback 98% > /dev/null 2>&1 || true &
#amixer -c 0 set PCM playback ${VOLUME}% > /dev/null 2>&1 || true &
