2025-02-14 23:10:09 +01:00

135 lines
3.0 KiB
Awk
Executable File

#!/usr/bin/awk -f
function get_parent(pid, cmd, ppid, arr) {
cmd = sprintf("/proc/%d/stat", pid)
ppid = ""
if ((getline line < cmd) > 0) {
split(line, arr)
ppid = arr[4]
}
close(cmd)
return ppid
}
function proc_clients(line, arr) {
if (match(line, /^Client #(.*)/, arr)) {
store_client()
client_index = arr[1]
return
}
else if (match(line, /^\s*application\.process\.id = "(.*)"/, arr)) {
process_id = arr[1]
return
}
else if (match(line, /^\s*application\.name = "(.*)"/, arr)) {
application_name = arr[1]
return
}
}
function store_client() {
if (client_index == "")
return
clients[client_index] = 1
clients[client_index, "pid"] = process_id
clients[client_index, "parent_pid"] = get_parent(process_id)
clients[client_index, "name"] = application_name
client_index = ""
process_id = ""
}
function proc_sink_inputs(line, arr) {
if (match(line, /^Sink Input #(.*)/, arr)) {
apply_sink_input()
sink_index = arr[1]
return
}
else if (match(line, /^\s*application\.process\.id = "(.*)"/, arr)) {
process_id = arr[1]
return
}
else if (match(line, /^\s*Client: (.*)/, arr)) {
client_index = arr[1]
return
}
else if (match(line, /^\s*Mute: (.*)/, arr)) {
muted = (arr[1] == "yes")
return
}
else if (match(line, /^\s*Volume:.* ([0-9]+)%/, arr)) {
volume = strtonum(arr[1])
return
}
}
function apply_sink_input( cmd, header, msg, inc) {
if (sink_index == "")
return
# Do stuff if PID matches
if (PID == clients[client_index, "pid"] || PID == clients[client_index, "parent_pid"]) {
switch (ACTION) {
case "-i":
case "-d":
inc = strtonum(ARG)
if (ACTION == "-i")
volume += inc
else
volume -= inc
volume = volume > 100 ? 100 : volume
volume = volume < 0 ? 0 : volume
cmd = sprintf("pactl set-sink-input-volume '%d' '%d'%", sink_index, volume)
system(cmd)
print cmd
break
case "-t":
muted = !muted
cmd = sprintf("pactl set-sink-input-mute '%d' '%s'", sink_index, muted ? "true" : "false")
system(cmd)
print cmd
break
}
# Display a "popup" with new volume
header = sprintf("Client Volume: %d%%%s", volume, muted ? " MUTED" : "")
msg = clients[client_index, "name"]
system(sprintf("notify-send -r 101 -u low -h 'int:value:%d' '%s' '%s'", volume, header, msg))
}
sink_index = ""
}
BEGIN {
# Get arguments
# ACTION: -d, -i or -t (like pamixer)
# ARG: num arg for -d or -i
ACTION = ARGV[1]
ARG = ARGV[2]
for (i = 1; i < ARGC; i++)
delete ARGV[i]
# Get client info
getline PID
getline TITLE # Not used
getline APPID # Not used
getline TAGS # Not used
getline GEOMETRY # Not used
if (PID == "")
exit 1
# Process PulseAudio clients list and store PIDs for each
cmd = "pactl list clients"
while ((cmd | getline line) > 0)
proc_clients(line)
close(cmd)
store_client()
# Process PulseAudio sink inputs list and run apply_sink_input() for each
cmd = "pactl list sink-inputs"
while ((cmd | getline line) > 0)
proc_sink_inputs(line)
close(cmd)
apply_sink_input()
}