#!/bin/bash

# volctl -- Simple shell tool to control pulseaudio volume
# Version: 0.1.0
# Author: binaryDiv

# Set bash strict mode
set -euo pipefail
IFS=$'\n\t'


# Default settings
# ----------------

SINK="@DEFAULT_SINK@"
DEFAULTSTEP="5%"
DEFAULTVOLUME="60%"
GUICOMMAND="pavucontrol"


# Define command functions
# ------------------------

usage() {
    cat << END_OF_HELPTEXT
Usage: $(basename $0) COMMAND [...]

Controls pulseaudio volume for default sink.

General commands:
  help             print this help message
  bash-completion  output bash completion code

Volume control:
  up [STEP%]       increase volume by STEP% (default: $DEFAULTSTEP)
  down [STEP%]     decrease volume by STEP% (default: $DEFAULTSTEP)
  set VOL%         set volume to VOL%
  set default      set volume to default value ($DEFAULTVOLUME)
  mute             mute sound output
  unmute           unmute sound output
  mute toggle      toggle mute

User interfaces:
  gui              open GUI tool ($GUICOMMAND)
END_OF_HELPTEXT
}

fail() {
    echo "$@"
    exit 1
}

vol_set() {
    local VALUE=$1
    pactl set-sink-volume "$SINK" "$VALUE"
}

vol_mute() {
    local OPTION=$1
    pactl set-sink-mute "$SINK" "$OPTION"
}

open_gui() {
    exec $GUICOMMAND
}

print_bash_completion() {
    cat << 'END_OF_BASHCOMPLETION'
# Use "source <(volctl bash-completion)" to activate bash completion.

_volctl() {
    COMPREPLY=()
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local commands="help up down set mute unmute gui"

    if [[ $COMP_CWORD -eq 1 ]]; then
        # First argument: command
        COMPREPLY=($(compgen -W "$commands" -- $cur))
    elif [[ $COMP_CWORD -eq 2 ]]; then
        # Second argument
        case "${COMP_WORDS[1]}" in
            set)
                compopt -o nosort
                COMPREPLY=($(compgen -W "default 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%" -- $cur))
            ;;
            mute)
                COMPREPLY=($(compgen -W "toggle" -- $cur))
            ;;
        esac
    fi
}
complete -F _volctl volctl
END_OF_BASHCOMPLETION
}

# Entrypoint
# ----------

main() {
    # Get command from arguments
    local COMMAND="${1:-}"

    case "$COMMAND" in
        help | --help | -h | '')
            usage
            exit 1
        ;;

        up)
            # Command: up [STEP%]
            local STEP="+${2:-$DEFAULTSTEP}"
            vol_set "$STEP"
        ;;

        down)
            # Command: down [STEP%]
            local STEP="-${2:-$DEFAULTSTEP}"
            vol_set "$STEP"
        ;;

        set)
            # Command: set VOL% | set default
            local VOL="${2:-}"
            if [[ -z $VOL ]]; then
                fail "Command 'set' needs an argument, see 'help'."
            elif [[ $VOL == 'default' ]]; then
                vol_set "$DEFAULTVOLUME"
            else
                vol_set "$VOL"
            fi
        ;;

        mute)
            # Command: mute | mute toggle
            local OPTION="${2:-}"
            if [[ -z $OPTION ]]; then
                vol_mute 1
            elif [[ $OPTION == 'toggle' ]]; then
                vol_mute toggle
            else
                fail "Unknown option '$OPTION' for command 'mute', see 'help'."
            fi
        ;;

        unmute)
            # Command: unmute
            vol_mute 0
        ;;

        gui)
            # Command: gui
            open_gui
        ;;

        bash-completion)
            # Command: bash-completion
            print_bash_completion
        ;;

        *)
            fail "Unknown command '$COMMAND', use 'help' to show all commands."
        ;;
    esac
}

main "$@"

