fant0men

Slowly and gradually lower system audio volume (script)

Jan 29th, 2020
130
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/bin/bash
  2. # This script slowly and gradually lowers the volume until it's equal to
  3. # 18% (11796). The script takes 1 hour (360 * 10 seconds) all in all, to
  4. # completely lower the volume to the target volume.
  5. # I'm using this script to automatically lower the volume when I fall
  6. # asleep to watching a movie or YouTube.
  7.  
  8. regex_sink='Sink #[0-9]+'
  9. regex_volume='^Volume:'
  10. target_volume='11796'
  11. interval='10'
  12.  
  13. # trap ctrl-c and call ctrl_c()
  14. trap ctrl_c INT
  15.  
  16. # If a SIGINT signal is captured, then put the volume back to where it
  17. # was before running this script.
  18. ctrl_c () {
  19.     pactl set-sink-volume 0 ${volume}
  20.     echo '** Trapped CTRL-C'
  21.     exit
  22. }
  23.  
  24. # Creates a function called 'get_volume', which gets the current volume.
  25. get_volume () {
  26.  
  27.     mapfile -t pulseaudio_info < <(pactl list sinks | sed -e 's/^[[:blank:]]*//' -e 's/ \+/ /g')
  28.  
  29.     for (( i = 0; i < ${#pulseaudio_info[@]}; i++ )); do
  30.  
  31.         line="${pulseaudio_info[${i}]}"
  32.  
  33.         if [[ $line =~ $regex_volume ]]; then
  34.  
  35.             volume=$(sed -E 's|Volume: front-left: ([0-9]+).*|\1|' <<<"$line")
  36.             break
  37.         fi
  38.     done
  39.  
  40.     echo "$volume"
  41. }
  42.  
  43. # Creates a function called 'get_count', which will get the exact number
  44. # to decrease the volume by every 10 seconds. Since Bash can't do
  45. # floating-point arithmetic, this becomes slightly tricky. Keep in mind
  46. # that Bash always rounds down, never up. I've chosen 354 as the unit
  47. # because then it'll be exactly 1 minute left to take care of potential
  48. # remaining value.
  49. get_count () {
  50.  
  51.     diff="$1"
  52.     unit='354'
  53.     count[0]=$(( diff / unit ))
  54.     test=$(( unit * ${count[0]} ))
  55.  
  56.     # If there's a remaining value, then divide that value by 5, which
  57.     # will be for 354-359.
  58.     if [[ $test -lt $diff ]]; then
  59.         tmp=$(( diff - test ))
  60.         count[1]=$(( tmp / 5 ))
  61.  
  62.         for n in {1..5}; do
  63.             tmp=$(( tmp - ${count[1]} ))
  64.         done
  65.  
  66.         # If there's still a remaining value, then set ${count[2]} to
  67.         # that value. This will be used for the last instance of running
  68.         # the 'pactl' command (and lowering the volume).
  69.         count[2]="$tmp"
  70.     else
  71.         count[1]='0'
  72.         count[2]='0'
  73.     fi
  74.  
  75.     echo "${count[@]}"
  76. }
  77.  
  78. # Creates a function called 'spin', which will show a simple animation,
  79. # while waiting for the command output.
  80. spin () {
  81.  
  82.     spinner=( '   ' '.  ' '.. ' '...' )
  83.  
  84.     while true; do
  85.  
  86.         for s in "${spinner[@]}"; do
  87.             echo -ne "\rWait${s}"
  88.             sleep 0.5
  89.         done
  90.     done
  91. }
  92.  
  93. volume=$(get_volume)
  94.  
  95. # If volume is greater than target volume, then...
  96. if [[ $volume -gt $target_volume ]]; then
  97.  
  98.     # Calculates the difference between current volume and target volume.
  99.     diff=$(( $volume - $target_volume ))
  100.  
  101.     # If the difference is greater than 360 (the unit used in this
  102.     # script), then run the get_count function, otherwise just decrease
  103.     # by 0 until the very last second, and then decrease volume by the
  104.     # full difference. There's no need to lower the volume gradually, if
  105.     # the difference is very small.
  106.     if [[ $diff -gt 360 ]]; then
  107.         count=( $(get_count ${diff}) )
  108.     else
  109.         count=(0 0 ${diff})
  110.     fi
  111.  
  112.     # Starts the spinner animation...
  113.     spin &
  114.     spin_pid="$!"
  115.  
  116.     # For the first 354 10-second intervals, lower the volume by the
  117.     # value in ${count[0]}
  118.     for n in {1..354}; do
  119.         sleep ${interval}
  120.         pactl set-sink-volume 0 -${count[0]}
  121.     done
  122.  
  123.     # For 354-359, lower the volume by the value in ${count[1]}
  124.     for n in {1..5}; do
  125.         sleep ${interval}
  126.         pactl set-sink-volume 0 -${count[1]}
  127.     done
  128.  
  129.     # Finally lower the volume by the value in ${count[2]}
  130.     sleep ${interval}
  131.     pactl set-sink-volume 0 -${count[2]}
  132.  
  133.     kill "$spin_pid"
  134.     echo
  135. fi
RAW Paste Data