aboutsummaryrefslogtreecommitdiffstats
path: root/bin/set_volume
blob: 1498dcc2f927470b75bda8e3d953f0eb33f0dc13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#!/usr/bin/env bash

set -eu

state_muted="${XDG_RUNTIME_DIR}/state_muted"
state_muted_headphone=""
state_muted_speaker=""
state_bt_headphone=""
name_bt_headphone="bluez_sink.00_1B_66_02_36_41"
cardselector=""
card_icon="/usr/share/icons/gnome/48x48/devices/audio-speakers.png" # gnome-icon-theme 
mute_state_on="[on]"
mute_state_off="[off]"

get_mute_state() {
  local name="$1"
  amixer -M -c "${cardselector}" sget "${name}" |grep -o '\[o[n|f]*\]' |head -n1
}

get_volume_percentage() {
  local name="$1"
  amixer -M -c "${cardselector}" sget "${name}" |grep -o '\[[0-9]*%*\]' |head -n1 |sed -e 's/\[//;s/\]//'
}

get_volume_db() {
  local name="$1"
  amixer -M -c "${cardselector}" sget "${name}" |grep -Eo '\[[-]?[0-9]+\.[0-9]+dB\]' |head -n1 |sed -e 's/\[//;s/\]//'
}

is_channel_available() {
  local name="$1"
  amixer -M -c "${cardselector}" sget "${name}" > /dev/null 2>&1
}

increase_volume() {
  amixer -M -c "${cardselector}" sset Master 5%+ &>/dev/null
  local state_master=""
  state_master=$(get_volume_percentage 'Master')
  #update pactl bluetooth audio to same level if present
  if [ "$state_bt_headphone" = "[on]" ]; then
    pactl set-sink-volume $name_bt_headphone "$state_master%"
  fi
  print_volumes
}

decrease_volume() {
  amixer -M -c "${cardselector}" sset Master 5%- > /dev/null
  local state_master=""
  state_master=$(get_volume_percentage 'Master')
  #update pactl bluetooth audio to same level if present
  if [ "$state_bt_headphone" = "[on]" ];then
    pactl set-sink-volume $name_bt_headphone "$state_master%"
  fi
  print_volumes
}

print_volumes() {
  local message=()
  if is_channel_available 'Master'; then
    message+=("🎚 $(get_volume_percentage 'Master') ($(get_volume_db 'Master'))")
  fi
  if is_channel_available 'Headphone'; then
    message+=("🎧 $(get_volume_percentage 'Headphone') ($(get_volume_db 'Headphone'))")
  fi
  if is_channel_available 'Speaker'; then
    message+=("🔈 $(get_volume_percentage 'Speaker') ($(get_volume_db 'Speaker'))")
  fi
  send_notify "${message[*]}"
}

mute_state_to_icon() {
  local state="$1"
  local icon=""
  if [[ "$state" == "$mute_state_on" ]]; then
    icon="🔊"
  fi
  if [[ "$state" == "$mute_state_off" ]]; then
    icon="🔇"
  fi
  echo "$icon"
}

print_mute_states() {
  local message=()
  if is_channel_available 'Master'; then
    message+=("🎚 [$(mute_state_to_icon "$(get_mute_state 'Master')")] $(get_volume_percentage 'Master') ($(get_volume_db 'Master'))")
  fi
  if is_channel_available 'Headphone'; then
    message+=("🎧 [$(mute_state_to_icon "$(get_mute_state 'Headphone')")] $(get_volume_percentage 'Headphone') ($(get_volume_db 'Headphone'))")
  fi
  if is_channel_available 'Speaker'; then
    message+=("🔈 [$(mute_state_to_icon "$(get_mute_state 'Speaker')")] $(get_volume_percentage 'Speaker') ($(get_volume_db 'Speaker'))")
  fi
  send_notify "${message[*]}"
}

toggle_volume() {
  local state_master=""
  local state_headphone=""
  local state_speaker=""
  if is_channel_available 'Master'; then
    state_master=$(get_mute_state 'Master')
  fi
  if is_channel_available 'Headphone'; then
    state_headphone=$(get_mute_state 'Headphone')
  fi
  if is_channel_available 'Speaker'; then
    state_speaker=$(get_mute_state 'Speaker')
  fi
  case "$state_master" in
    "${mute_state_on}")
      amixer -M -c "${cardselector}" sset Master mute &>/dev/null
      state_master="[off]"
      # if headphones are off already, don't mute, instead save state to tmp file
      if [ "$state_headphone" = "[off]" ];then
        echo "headphone [off]" >> "$state_muted"
      else
        amixer -M -c "${cardselector}" sset Headphone mute &>/dev/null
        state_headphone="[off]"
      fi
      # if speakers are off already, don't mute, instead save state to tmp file
      if [ "$state_speaker" = "[off]" ];then
        echo "speaker [off]" >> "$state_muted"
      else
        amixer -M -c "${cardselector}" sset Speaker mute &>/dev/null
        state_speaker="[off]"
      fi
      # if present, also mute bluetooth headphone
      if [ "$state_bt_headphone" = "[on]" ]; then
        pactl set-sink-mute $name_bt_headphone 1
      fi
    ;;
    "${mute_state_off}")
      amixer -M -c "${cardselector}" sset Master unmute &>/dev/null
      state_master="[on]"
      # if headphones are meant to be off, don't unmute them again
      if [ "$state_muted_headphone" != "[off]" ];then
        amixer -M -c "${cardselector}" sset Headphone unmute &>/dev/null
        state_headphone="[on]"
      fi
      # if headphones are meant to be off, don't unmute them again
      if [ "$state_muted_speaker" != "[off]" ];then
        amixer -M -c "${cardselector}" sset Speaker unmute &>/dev/null
        state_speaker="[on]"
      fi
      # if present, also unmute bluetooth headphone
      if [ "$state_bt_headphone" = "[on]" ]; then
        pactl set-sink-mute $name_bt_headphone 0
      fi
    ;;
  esac
  print_mute_states
}

send_notify() {
  local timeout=1000
  notify-send -t $timeout -i "${card_icon}" "Volume" "$1"
}

if [[ "$HOSTNAME" == "dvzrv" ]]; then
  cardselector="1"
  if [ -n "$(pactl list sinks short | grep $name_bt_headphone)" ]; then
    state_bt_headphone="[on]"
  fi
  #TODO: also check pactl for JACK sink
fi
if [[ "$HOSTNAME" == "hmbx" ]]; then
  cardselector="1"
fi

if pgrep jack > /dev/null; then
  echo "JACK is running"
fi

case "$1" in
  "increase" | "up" | "+" )
    increase_volume
    ;;
  "decrease" | "down" | "-" )
    decrease_volume
    ;;
  "toggle")
    if [ -f "$state_muted" ]; then
      set +e
      state_muted_speaker="$(cat "$state_muted" | grep speaker | cut -d' ' -f2)"
      state_muted_headphone="$(cat "$state_muted" | grep headphone | cut -d' ' -f2)"
      set -e
      rm "$state_muted"
    else
      touch "$state_muted"
    fi
    toggle_volume
    ;;
  *)
    ;;
esac

exit 0