Skip to content

Commit

Permalink
Merge pull request #71 from marioortizmanero/latency-flag
Browse files Browse the repository at this point in the history
Add --listen-timeout-secs
  • Loading branch information
marioortizmanero authored Jul 13, 2022
2 parents 0221de3 + 9eeb5f8 commit 889c005
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
49 changes: 49 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,55 @@ font-Y = Font Awesome 5 Brands: pixelsize=11
font-Z = Material Icons: style=Regular: pixelsize=13; 2
```

## FAQ

### Can I use this with a status bar other than Polybar?

The only part of this script that's tied to Polybar is the color formatting.
When muted, the dimmed color will probably not work. Please [let us know in this
issue](https://github.com/marioortizmanero/polybar-pulseaudio-control/issues/36)
if you want support for a new status bar. I'd strongly recommend you to open a
PR yourself, as it should be relatively easy!

### Does this work with PipeWire?

Yes! You only need to install the pulseaudio client on your machine. On Arch
Linux, that's
[`pipewire-pulse`](https://archlinux.org/packages/extra/x86_64/pipewire-pulse/),
for example.

It won't work with other audio servers like JACK, though.

### This script uses too much CPU

We use the `pactl subscribe` command to get notified of new events that may
occur in order to refresh the output. However, the command often outputs *a lot*
of events for a simple action, like increasing the volume. Instead of refreshing
for every single line it prints, we:

1. Wait for one event
2. Update the output first
3. Continue to listen for events until a timeout ends, or until we reach a large
enough number of them
4. Update the output again
5. Go back to step 1

This way, the first event will update quickly, and the following ones, which are
most likely unnecessary, will be ignored until some time passes. This reduces
the CPU usage, but it's not really perfect, as everyone percieves latency
differently, and it depends on the use-case.

The timer can be configured with `--listen-timeout-secs`, which has a default
value of `0.05` (50 ms). If you want less CPU usage, i.e., ignore more duplicate
events, you can bump it to, for example, `0.1` (100 ms). Or for faster refreshes
when performing multiple actions quickly, e.g., updating the volume with your
mousewheel, you can even use a smaller value.

### This script feels laggy when performing multiple actions quickly

Please refer to the previous question, as you can fix this by setting a smaller
refresh delay with `--listen-timeout-secs`.

## Sources

Part of the script and of this README's info was taken from [customlinux.blogspot.com](http://customlinux.blogspot.com/2013/02/pavolumesh-control-active-sink-volume.html), the creator. It was later adapted to fit polybar. It is also mixed with [the ArcoLinux version](https://github.com/arcolinux/arcolinux-polybar/blob/master/etc/skel/.config/polybar/scripts/pavolume.sh), which implemented the `listen` action to use less resources.
Expand Down
18 changes: 17 additions & 1 deletion pulseaudio-control.bash
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ OSD="no"
NODE_NICKNAMES_PROP=
VOLUME_STEP=2
VOLUME_MAX=130
LISTEN_TIMEOUT=0.05
# shellcheck disable=SC2016
FORMAT='$VOL_ICON ${VOL_LEVEL}% $ICON_NODE $NODE_NICKNAME'
declare -A NODE_NICKNAMES
Expand Down Expand Up @@ -348,7 +349,7 @@ function listen() {
# Read all stdin to flush unwanted pending events, i.e. if there are
# 15 events at the same time (100ms window), output is only called
# twice.
read -r -d '' -t 0.1 -n 10000
read -r -d '' -t "$LISTEN_TIMEOUT" -n 10000

# After the 100ms waiting time, output again the state, as it may
# have changed if the user did an action during the 100ms window.
Expand Down Expand Up @@ -466,6 +467,17 @@ Options:
Exact matches are prioritized. Don't forget to quote the string when
using globs, to avoid unwanted shell glob extension.
Default: none
--listen-timeout-secs
The listen command updates the output as soon as it receives an event
from PulseAudio. However, events are often accompanied by many other
useless ones, which may result in unnecessary consecutive output
updates. This script buffers the following events until a timeout is
reached to avoid this scenario, which lessens the CPU load on events.
However, this may result in noticeable latency when performing many
actions quickly (e.g., updating the volume with the mouse wheel). You
can specify what timeout to use to control the responsiveness, in
seconds.
Default: \"$LISTEN_TIMEOUT\"
Actions:
help display this message and exit
Expand Down Expand Up @@ -570,6 +582,10 @@ while [[ "$1" = --* ]]; do
NODE_TYPE="$val"
SINK_OR_SOURCE=$([ "$NODE_TYPE" == "output" ] && echo "ink" || echo "ource")
;;
--listen-timeout-secs)
if getOptVal "$@"; then shift; fi
LISTEN_TIMEOUT="$val"
;;
# Deprecated options, to be removed in a next release
--icon-sink)
echo "Replaced by --icon-node, see https://github.com/marioortizmanero/polybar-pulseaudio-control/releases/tag/v3.0.0" >&2
Expand Down

0 comments on commit 889c005

Please sign in to comment.