#!/bin/env bash

init (){
	case $1 in
		"sink")
			sink=$2
			pactl list sinks short | grep $sink && exit
			pactl load-module module-null-sink sink_name=$sink sink_properties="device.description="$sink""
		;;
		"source")
			source=$2
			pactl list sources short | grep $source && exit
			pactl load-module module-null-sink sink_name=$source"_sink" sink_properties=device.description=$source"_sink"
			pactl load-module module-remap-source source_name=$source master=$source"_sink.monitor" source_properties=device.description=$source 
		;;
	esac
	
}

connect (){
	vi=$1
	ho=$2
	latency=${3:-200}

	[ -z "$vi" -o -z "$ho" ] && exit
	LC_ALL=C pactl list modules | grep -B 2 "$ho source=$vi" >/dev/null || \
	pactl load-module module-loopback sink=$ho source=$vi sink_dont_move=true source_dont_move=true latency_msec=$latency
}

disconnect (){
	vi=$1
	ho=$2

	[ -z "$vi" -o -z "$ho" ] && exit
	index="$(LC_ALL=C pactl list modules | grep -B 2 "$ho source=$vi" | grep Module | sed 's/.*#//g')"
	[ -z "$index" ] || pactl unload-module $index
}

remove (){
	vi=$1

	#index="$(pacmd list-modules | grep -B 2 "$vi>" | grep index | sed 's/[^0-9]*//g')"
	index="$(LC_ALL=C pactl list modules | grep -B 2 "$vi " | grep Module | sed 's/.*#//g')"
	[ -z "$index" ] || pactl unload-module $index
}

mute (){
	device_type=$1
	device=$2
	status=$3

	pactl set-$device_type-mute $device $status
}

volume (){
	vi=$2
	[ -z $vi ] && exit
	pactl set-$1-volume $vi $3%
}

rename () {
	pacmd update-sink-proplist $1 device.description=$2

}

get (){
		eval "j="\$$2""
		[ "$1" = "vol" ] && [ -z $j ] && echo 0
		[ -z $j ] &&  return
		case $1 in
			"sink")
				aux=$(pacmd list-sinks | grep -A 50 $j | grep alsa.card.name | sed 's/.*= //g; s/"//g')
			;;
			"virtual_sink")
				aux=$(pacmd list-sinks | grep $j >/dev/null && echo $j)
			;;
			"src")
				aux=$(pacmd list-sources | grep -A 37 $j | grep alsa.card_name | sed 's/.*= //g; s/"//g')
			;;
			"virtual_src")
				aux=$(pacmd list-sources | grep $j >/dev/null && echo $j)
			;;
			"vol")
				aux=$(pactl list $3 | grep -A 7 $j | tr ' ' '\n' | grep -m1 '%' | tr -d '%')
				[ -z $aux ]
				echo $aux
				exit
			;;
		esac

		if [ -z "$aux" ]; then 
			[ -z $3 ] && eval "echo "\$$2""
		else
			echo $aux
		fi

}

list (){
	if which pulseaudio > /dev/null 2>&1; then
		if [ "$1" = 'sinks' ]; then
			list=$(LC_ALL=C pactl list sinks | awk '/Name:/ {print $0} /Driver:/ {print $0} /Description/ {print $0};' | tac | sed -e '/null/,+2d; /ladspa/,+2d; /module/d; s/.*: //g' | tac)
		else
			list=$(LC_ALL=C pactl list sources | awk '/Name:/ {print $0} /Driver:/ {print $0} /Description/ {print $0};' | tac | sed -e '/null/,+2d; /remap/,+2d' | tac | sed '/.monitor/,+2d; /module/d; s/.*: //g')
		fi
	else
		if [ "$1" = 'sinks' ]; then
			list=$(LC_ALL=C pactl list sinks | awk '/Name:/ {print $0} /device.description/ {print $0} /factory.name = / {print $0} ;' | sed 's/.*<//g; s/>//; s/.*= //g; s/"//g' | tac | sed -e '/null/,+2d' | tac | sed 's/.*: //g; /sink/d')
		else
			list=$(LC_ALL=C pactl list sources | awk '/Name:/ {print $0} /Description/ {print $0} /node.group = / {print $0} ;' | sed -e '/monitor/,+1d' | tac | sed -e '/node.group/,+2d; s/.*: //g' | tac)
		fi
	fi
	echo "$list"
}

move_sink_input_master (){
	sink_name=$1
	master=$2
	index=$(LC_ALL=C pactl list modules | grep -B 2 "$sink_name m" | grep Module | sed 's/.*#//g')
	[ -z "$index" ] && exit
	id=$(LC_ALL=C pactl list sink-inputs | grep -B 2 $index | grep '#' | sed 's/.*#//g')
	[ -z "$id" ] && exit
	pactl move-sink-input $id $master
}

eq (){
	sink_name=$1
	master=$2
	control=$3
	label=mbeq
	plugin=mbeq_1197

	for i in '/usr/lib/ladspa' '/usr/local/lib/ladspa'; do
		[ -f "$i/$plugin.so" ] && found=1
	done

	[ -z "$found" ] && exit

	info="$(LC_ALL=C pactl list modules | grep -B 2 "$sink_name m")"
	if ! [ -z "$info" ]; then
		index=$(echo "$info" | grep Module | sed 's/.*#//g')
		if ! [ -z "$index" ]; then
			old_control=$(echo "$info" | grep control | sed 's/.*control=//g')
			[ "$control" = "$old_control" ] && exit
			pactl unload-module $index
		fi
	fi

	[ "$master" = "remove" ] && exit

	pactl load-module module-ladspa-sink \
		sink_properties=device.description=$sink_name \
		sink_name=$sink_name	\
		master=$master			\
		plugin=mbeq_1197		\
		label=mbeq				\
		control=$control
}

compressor (){
	sink_name=$1
	master=$2
	control=$3

	#LC_ALL=C pactl list modules | grep "$sink_name" >/dev/null || \
	index=$(LC_ALL=C pactl list modules | grep -B 2 "$sink_name m" | grep Module | sed 's/.*#//g')
	[ -z "$index" ] || pactl unload-module $index

	[ "$master" = "remove" ] && exit

	pactl load-module module-ladspa-sink \
		sink_properties=device.description=$sink_name \
		sink_name=$sink_name	\
		master=$master			\
		plugin=sc4m_1916		\
		label=sc4m				\
		control=$control
}

rnnoise() {
	sink_name=$1
	master=$2
	control=$3
	status=$4
	latency=${5:-200}

	label=noisetorch
	plugin=rnnoise_ladspa
 
	for i in '/usr/lib/ladspa' '/usr/local/lib/ladspa'; do
		[ -f "$i/$plugin.so" ] && found=1
	done

	[ -z "$found" ] && exit 1

	if [ "$status" = "connect" ]; then
		pactl list sinks short | grep "$sink_name.*null" > /dev/null && exit
		pactl load-module module-null-sink sink_name=$sink_name

		pactl load-module module-ladspa-sink master=$sink_name sink_name=$sink_name"_in" label=noisetorch plugin=rnnoise_ladspa control=$control
		#pactl load-module module-ladspa-sink master=$sink_name sink_name=$sink_name"_in" label=noise_suppressor_mono plugin=librnnoise_ladspa control=$control
		pactl load-module module-loopback sink=$sink_name"_in" source=$master latency_msec=$latency source_dont_move=true sink_dont_move=true
	else
		index=$(LC_ALL=C pactl list modules | grep -B 2 noise | grep -B 2 -A 1 ladspa | grep Module | sed 's/.*#//g')
		[ -z "$index" ] || pactl unload-module $index

		index=$(LC_ALL=C pactl list modules | awk '/Module/{print $0} /Name:/ {print $0} /Argument/' | grep -B 2 $sink_name | grep -B 1 null | grep Module | sed 's/.*#//g')
		[ -z "$index" ] || pactl unload-module $index
	fi
}


case $1 in
	"init")
		init $2 $3
	;;
	"connect") 
		connect $2 $3 $4
	;;
	"disconnect")
		disconnect $2 $3 $4
	;;
	"remove")
		remove $2 $3
	;;
	"volume")
		volume $2 $3 $4
	;;
	"get")
		get $2 $3 $4
	;;
	"list")
		list $2
	;;
	"rename")
		rename $2 $3
	;;
	"mute")
		mute $2 $3 $4
	;;
	"move_sink_input_master")
		move_sink_input_master $2 $3
	;;
	"eq")
		eq $2 $3 $4
	;;
	"compressor")
		compressor $2 $3 $4
	;;
	"rnnoise")
		rnnoise $2 $3 $4 $5 $6
	;;
	"*") echo "command not found";;
esac
