1
1
#! /usr/bin/env sh
2
2
3
+ # Source global control script
3
4
scrDir=$( dirname " $( realpath " $0 " ) " )
4
- source $scrDir /globalcontrol.sh
5
-
6
- # define functions
7
-
8
- print_error () {
9
- cat << "EOF "
10
- ./volumecontrol.sh -[device] <actions>
11
- ...valid device are...
12
- i -- input device
13
- o -- output device
14
- p -- player application
15
- ...valid actions are...
16
- i -- increase volume [+5]
17
- d -- decrease volume [-5]
18
- m -- mute [x]
5
+ source " $scrDir /globalcontrol.sh"
6
+
7
+ # Check if SwayOSD is installed
8
+ use_swayosd=false
9
+ if command -v swayosd-client > /dev/null 2>&1 && pgrep -x swayosd-server > /dev/null; then
10
+ use_swayosd=true
11
+ fi
12
+
13
+ # Define functions
14
+
15
+ print_usage () {
16
+ cat << EOF
17
+ Usage: $( basename " $0 " ) -[device] <action> [step]
18
+
19
+ Devices/Actions:
20
+ -i Input device
21
+ -o Output device
22
+ -p Player application
23
+ -s Select output device
24
+ -t Toggle to next output device
25
+
26
+ Actions:
27
+ i Increase volume
28
+ d Decrease volume
29
+ m Toggle mute
30
+
31
+ Optional:
32
+ step Volume change step (default: 5)
33
+
34
+ Examples:
35
+ $( basename " $0 " ) -o i 5 # Increase output volume by 5
36
+ $( basename " $0 " ) -i m # Toggle input mute
37
+ $( basename " $0 " ) -p spotify d 10 # Decrease Spotify volume by 10
38
+ $( basename " $0 " ) -p '' d 10 # Decrease volume by 10 for all players
39
+
19
40
EOF
20
41
exit 1
21
42
}
22
43
23
44
notify_vol () {
24
- angle=" $(( (($vol + 2 ) / 5 ) * 5 )) "
45
+ angle=$(( (($vol + 2 ) / 5 ) * 5 ))
25
46
ico=" ${icodir} /vol-${angle} .svg"
26
47
bar=$( seq -s " ." $(( $vol / 15 )) | sed ' s/[0-9]//g' )
27
48
notify-send -a " t2" -r 91190 -t 800 -i " ${ico} " " ${vol}${bar} " " ${nsink} "
@@ -37,78 +58,106 @@ notify_mute() {
37
58
fi
38
59
}
39
60
40
- action_pamixer () {
41
- pamixer " ${srce} " -" ${1} " " ${step} "
42
- vol=$( pamixer " ${srce} " --get-volume | cat)
61
+ change_volume () {
62
+ local action=$1
63
+ local step=$2
64
+ local device=$3
65
+ local delta=" -"
66
+ local mode=" --output-volume"
67
+
68
+ [ " ${action} " = " i" ] && delta=" +"
69
+ [ " ${srce} " = " --default-source" ] && mode=" --input-volume"
70
+ case $device in
71
+ " pamixer" )
72
+ $use_swayosd && swayosd-client ${mode} " ${delta}${step} " && exit 0
73
+ pamixer $srce -" $action " " $step "
74
+ vol=$( pamixer $srce --get-volume)
75
+ ;;
76
+ " playerctl" )
77
+ playerctl --player=" $srce " volume " $( awk -v step=" $step " ' BEGIN {print step/100}' ) ${delta} "
78
+ vol=$( playerctl --player=" $srce " volume | awk ' { printf "%.0f\n", $0 * 100 }' )
79
+ ;;
80
+ esac
81
+
82
+ notify_vol
43
83
}
44
84
45
- action_playerctl () {
46
- [ " ${1} " == " i" ] && pvl=" +" || pvl=" -"
47
- playerctl --player=" ${srce} " volume " 0.0${step}${pvl} "
48
- vol=$( playerctl --player=" ${srce} " volume | awk ' { printf "%.0f\n", $0 * 100 }' )
85
+ toggle_mute () {
86
+ local device=$1
87
+ local mode=" --output-volume"
88
+ [ " ${srce} " = " --default-source" ] && mode=" --input-volume"
89
+ case $device in
90
+ " pamixer" )
91
+ $use_swayosd && swayosd-client " ${mode} " mute-toggle && exit 0
92
+ pamixer $srce -t
93
+ notify_mute
94
+ ;;
95
+ " playerctl" )
96
+ local volume_file=" /tmp/$( basename " $0 " ) _last_volume_${srce:- all} "
97
+ if [ " $( playerctl --player=" $srce " volume | awk ' { printf "%.2f", $0 }' ) " != " 0.00" ]; then
98
+ playerctl --player=" $srce " volume | awk ' { printf "%.2f", $0 }' > " $volume_file "
99
+ playerctl --player=" $srce " volume 0
100
+ else
101
+ if [ -f " $volume_file " ]; then
102
+ last_volume=$( cat " $volume_file " )
103
+ playerctl --player=" $srce " volume " $last_volume "
104
+ else
105
+ playerctl --player=" $srce " volume 0.5 # Default to 50% if no saved volume
106
+ fi
107
+ fi
108
+ notify_mute
109
+ ;;
110
+ esac
49
111
}
50
112
51
113
select_output () {
52
- if [ " $@ " ] ; then
53
- desc= " $* "
54
- device=$( pactl list sinks | grep -C2 -F " Description: $desc " | grep Name | cut -d: -f2 | xargs)
114
+ local selection= $1
115
+ if [ -n " $selection " ] ; then
116
+ device=$( pactl list sinks | grep -C2 -F " Description: $selection " | grep Name | cut -d: -f2 | xargs)
55
117
if pactl set-default-sink " $device " ; then
56
- notify-send -t 2000 -r 2 -u low " Activated: $desc "
118
+ notify-send -t 2000 -r 2 -u low " Activated: $selection "
57
119
else
58
- notify-send -t 2000 -r 2 -u critical " Error activating $desc "
120
+ notify-send -t 2000 -r 2 -u critical " Error activating $selection "
59
121
fi
60
122
else
61
- pactl list sinks | grep -ie " Description:" | awk -F ' : ' ' {print $2}' | sort |
62
- while IFS= read -r x; do echo " $x " ; done
123
+ pactl list sinks | grep -ie " Description:" | awk -F ' : ' ' {print $2}' | sort
63
124
fi
64
125
}
65
126
66
- # eval device option
67
-
68
- while getopts iop:s: DeviceOpt; do
69
- case " ${DeviceOpt} " in
70
- i)
71
- nsink=$( pamixer --list-sources | awk -F ' "' ' END {print $(NF - 1)}' )
72
- [ -z " ${nsink} " ] && echo " ERROR: Input device not found..." && exit 0
73
- ctrl=" pamixer"
74
- srce=" --default-source"
75
- ;;
76
- o)
77
- nsink=$( pamixer --get-default-sink | awk -F ' "' ' END{print $(NF - 1)}' )
78
- [ -z " ${nsink} " ] && echo " ERROR: Output device not found..." && exit 0
79
- ctrl=" pamixer"
80
- srce=" "
81
- ;;
82
- p)
83
- player_name=" ${OPTARG} "
84
- nsink=$( playerctl --list-all | grep -w " ${player_name} " )
85
- [ -z " ${nsink} " ] && echo " ERROR: Player ${player_name} not active..." && exit 0
86
- ctrl=" playerctl"
87
- srce=" ${player_name} "
88
- ;;
89
- s)
90
- default_sink=" $( pamixer --get-default-sink | awk -F ' "' ' END{print $(NF - 1)}' ) "
91
- export selected_sink=" $( select_output " ${@ } " | rofi -dmenu -select " ${default_sink} " -config " ${confDir} /rofi/notification.rasi" ) "
92
- select_output " $selected_sink "
93
- exit
94
- ;;
95
- * ) print_error ;;
96
- esac
97
- done
127
+ toggle_output () {
128
+ local default_sink=$( pamixer --get-default-sink | awk -F ' "' ' END{print $(NF - 1)}' )
129
+ mapfile -t sink_array < <( select_output)
130
+ local current_index=$( printf ' %s\n' " ${sink_array[@]} " | grep -n " $default_sink " | cut -d: -f1)
131
+ local next_index=$(( (current_index % ${# sink_array[@]} ) + 1 ))
132
+ local next_sink=" ${sink_array[next_index-1]} "
133
+ select_output " $next_sink "
134
+ }
98
135
99
- # set default variables
136
+ # Main script logic
100
137
138
+ # Set default variables
101
139
icodir=" ${confDir} /dunst/icons/vol"
102
- shift $(( OPTIND - 1 ))
103
- step=" ${2:- 5} "
140
+ step=5
141
+ # Parse options
142
+ while getopts " iop:st" opt; do
143
+ case $opt in
144
+ i) device=" pamixer" ; srce=" --default-source" ; nsink=$( pamixer --list-sources | awk -F ' "' ' END {print $(NF - 1)}' ) ;;
145
+ o) device=" pamixer" ; srce=" " ; nsink=$( pamixer --get-default-sink | awk -F ' "' ' END{print $(NF - 1)}' ) ;;
146
+ p) device=" playerctl" ; srce=" ${OPTARG} " ; nsink=$( playerctl --list-all | grep -w " $srce " ) ;;
147
+ s) select_output " $( select_output | rofi -dmenu -config " ${confDir} /rofi/notification.rasi" ) " ; exit ;;
148
+ t) toggle_output; exit ;;
149
+ * ) print_usage ;;
150
+ esac
151
+ done
104
152
105
- # execute action
153
+ shift $(( OPTIND - 1 ))
106
154
107
- case " ${1} " in
108
- i) action_${ctrl} i ;;
109
- d) action_${ctrl} d ;;
110
- m) " ${ctrl} " " ${srce} " -t && notify_mute && exit 0 ;;
111
- * ) print_error ;;
112
- esac
155
+ # Check if device is set
156
+ [ -z " $device " ] && print_usage
113
157
114
- notify_vol
158
+ # Execute action
159
+ case $1 in
160
+ i|d) change_volume " $1 " " ${2:- $step } " " $device " ;;
161
+ m) toggle_mute " $device " ;;
162
+ * ) print_usage ;;
163
+ esac
0 commit comments