#!/bin/bash
#
# SwapOutput 1.4.20150427
#   Script made for controlling outputs for Asus Xonar Essence STX (and maybe other cards) in CLI for PulseAudio.
#   Useful for desktop icon(s) (shortcut(s) to switch between outputs).
#   Made by Ole-Henrik Jakobsen CC BY-SA.
#
# Usage:
#  ./swapoutput help | usage | --help | --usage
#
# Requirements: pulseaudio, awk, sed
# Optional:     zenity (recommended)
#
# Set some variables of your choice:
SET_VOLUME=35                         # Set the default volume if none is chosen, must have a value from 0-100.
SET_DEVICE_BUSPATH=""                 # [optional] To set default device (instead of being asked if multiple choices).
                                      # Find device.bus_path of your card (command: "pactl list sinks" will guide you there).
                                      # Replace colons (:) with underscores (_): Ex: "pci-0000:00:00.0" to "pci-0000_00_00.0"
ZENITY=/usr/bin/zenity                # [optional] Set location to zenity. This will be used if nothing is specified behind the file.

# Card profiles and sink ports specified by the card, default settings is based on Asus Xonar Essence STX but might work with other cards.
HEADPHONES_CARDPROFILE="output:analog-stereo+input:analog-stereo"
HEADPHONES_SINKPORT="analog-output;output-headphones-1"
HEADPHONESFRONT_CARDPROFILE="output:analog-stereo+input:analog-stereo"
HEADPHONESFRONT_SINKPORT="analog-output;output-headphones-2"
SPEAKERS_CARDPROFILE="output:analog-stereo+input:analog-stereo"
SPEAKERS_SINKPORT="analog-output;output-speaker"
DIGITAL_CARDPROFILE="output:iec958-stereo+input:analog-stereo"
DIGITAL_SINKPORT="iec958-stereo-output"

# Getting list of sink(s) and count them, excludes sinks with "hdmi" in them to reduce useless sinks for this script.
SINKS=`pactl list sinks short | grep "$SET_DEVICE_BUSPATH" | grep -v hdmi` # Get the list
COUNT=`pactl list sinks short | grep "$SET_DEVICE_BUSPATH" | grep -v hdmi | wc -l` # Count them (if more, you must specify)

if [ $COUNT -gt 1 ]
then
	if [ -f $ZENITY ];
	then
		CHOSEN=`$ZENITY --list --title="Set default sink" --text="Select which device to use as default sink" --column="" --column="Name" --column="Driver" --column="Bitrate" --column="Channels" --column="Samples" --column="State" --radiolist --width="1000" --height="200" $SINKS`
	else
		echo "Multiple sinks available:"
		echo "- please install zenity to choose from a list"
		echo "- or set device bus path in file manually (recommended)."
		exit 0
	fi
fi

if [ $CHOSEN ]
then
	SINK=`echo $CHOSEN`
        pacmd set-default-sink $CHOSEN
	sleep 0.1
else
	SINK=`echo $SINKS | awk '{ print $2 }'`
fi

# Detect running device and sink
#SINK=`pactl list sinks short | grep RUNNING | awk '{ print $2 }'` # You will notice repeats of this in the script, but they are necesarry as the sink changes when another card profile is loaded.
DEVP=`echo $SINK | sed 's/^alsa_output.//g' | sed 's/\.[^.]*$//'`
CARD=`pactl list short cards | grep $DEVP | colrm 2`

# Uncomment lines under to check if the script catch the correct data, good for debugging.
#echo "
#*****
#Sinks available:
#$SINKS
#
#Chosen card number:     $CARD
#Chosen sink:            $SINK
#Chosen device bus path: $DEVP
#*****
#"

if [ $1 ]
then
        SET_DEVICE=$1
else
	if [ -f $ZENITY ];
        then
                SET_DEVICE=`$ZENITY --list --title="Select output" --text="Select which output to use" --print-column="2" --hide-column="2" --column="" --column="dev" --column="Name" --radiolist --height="250" --width="300" \
                false headphones "Headphones" \
                false headphones_front "Headphones (front panel)" \
                false speakers "Speakers" \
                false digital "Digital" \
		true kill "Restart PulseAudio"`
	fi
fi

if [ $2 ]
then
	SET_VOLUME=$2
fi

# The script itself
case "$SET_DEVICE" in
  kill)
	pulseaudio -k
	echo "PulseAudio killed."
	exit 1
	;;
  volume)
	pactl set-sink-volume $SINK -- $SET_VOLUME%
        echo "Volum adjusted to: $SET_VOLUME%"
	exit 1
        ;;
  headphones)
        echo -n "Loaded: "
        pactl set-card-profile $CARD output:analog-stereo+input:analog-stereo
        echo -n "card profile"
        SINK=`pactl list sinks short | grep $DEVP | awk '{ print $2 }'`
        pactl set-sink-volume $SINK 0%
	sleep 0.1
        pactl set-sink-port $SINK "analog-output;output-headphones-1"
        echo -n ", sink port. Adjusting volume: "
        VOLUME=0
        while [ "$VOLUME" -lt $SET_VOLUME ]; do
                sleep 0.1
                let VOLUME=VOLUME+5
                pactl set-sink-volume $SINK $VOLUME%
                echo -n "$VOLUME% "
        done
        echo "- Output changed to: $SET_DEVICE"
	exit 1
        ;;
  headphones_front)
	echo -n "Loaded: "
	pactl set-card-profile $CARD output:analog-stereo+input:analog-stereo
	echo -n "card profile"
	SINK=`pactl list sinks short | grep $DEVP | awk '{ print $2 }'`
	pactl set-sink-volume $SINK 0%
	sleep 0.1
	pactl set-sink-port $SINK "analog-output;output-headphones-2"
        echo -n ", sink port. Adjusting volume: "
        VOLUME=0
        while [ "$VOLUME" -lt $SET_VOLUME ]; do
                sleep 0.1
                let VOLUME=VOLUME+5
                pactl set-sink-volume $SINK $VOLUME%
                echo -n "$VOLUME% "
        done
	echo "- Output changed to: $SET_DEVICE"
	exit 1
        ;;
  speakers)
	echo -n "Loaded: "
	pactl set-card-profile $CARD output:analog-stereo+input:analog-stereo
	echo -n "card profile"
        SINK=`pactl list sinks short | grep $DEVP | awk '{ print $2 }'`
	pactl set-sink-volume $SINK 0%
	sleep 0.1
	pactl set-sink-port $SINK "analog-output;output-speaker"
        echo -n ", sink port. Adjusting volume: "
        VOLUME=0
        while [ "$VOLUME" -lt 100 ]; do
                sleep 0.2
                let VOLUME=VOLUME+10
                pactl set-sink-volume $SINK $VOLUME%
                echo -n "$VOLUME% "
        done
        echo "- Output changed to: $SET_DEVICE"
	exit 1
	;;
  digital)
	echo -n "Loaded: "
	pactl set-card-profile $CARD output:iec958-stereo+input:analog-stereo
	echo -n "card profile"
	SINK=`pactl list sinks short | grep $DEVP | awk '{ print $2 }'`
	pactl set-sink-volume $SINK 0%
	sleep 0.1
	pactl set-sink-port $SINK iec958-stereo-output
	echo -n ", sink port. Adjusting volume: "
	VOLUME=0
	while [ "$VOLUME" -lt 100 ]; do
		sleep 0.2
		let VOLUME=VOLUME+10
		pactl set-sink-volume $SINK $VOLUME%
		echo -n "$VOLUME% "
	done
	echo "- Output changed to: $SET_DEVICE"
	exit 1
	;;
  *)
	echo "Usage:"
	echo "  ./mixerswap  [volume]     enter none for GUI."
	echo "    commands:"
	echo "      volume                         set absolute volume from 0-100, or relative volume (ex. +5). Values in percent."
	echo "      headphones [volume]            set output to headphone 6,3mm jack with optional (recommended) volume."
	echo "      headphones_front [volume]      set output to headphone front panel with optional (recommended) volume."
	echo "      speakers                       set output to RCA analog."
	echo "      digital                        set output to RCA digital/COAX."
	echo "    volume:"
	echo "      speakers|digital:              volume increases from 0% to 100% automagically."
	echo "      headphones(_front):            volume increases from 0% to any given level [volume] automagically to the nearest 5% rounded up."
	exit 0
	;;
esac

exit 0