docs: cut the readme down, fold the details
This commit is contained in:
1 parent
9f07150643
commit
bf4c172ac0
1 file changed
+46
-126
@@ -4,15 +4,15 @@
|
|||||||
|
|
||||||
<h1 align="center">bt-volume-step</h1>
|
<h1 align="center">bt-volume-step</h1>
|
||||||
|
|
||||||
<h3 align="center">Fixed volume steps for Bluetooth audio devices on PipeWire.</h3>
|
<h3 align="center">Clean volume steps for Bluetooth headphones and speakers.</h3>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
One press or swipe on your earbuds or speaker becomes one clean step on your volume slider.
|
One press or swipe on your device becomes one clean step on your volume slider.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h5 align="center">
|
<h5 align="center">
|
||||||
<a href="#usage">How to use</a> |
|
<a href="#install">Install</a> |
|
||||||
<a href="#installation">Install</a> |
|
<a href="#how-to-use">How to use</a> |
|
||||||
<a href="https://github.com/LoonixTools/bt-volume-step/issues">Report a bug</a>
|
<a href="https://github.com/LoonixTools/bt-volume-step/issues">Report a bug</a>
|
||||||
</h5>
|
</h5>
|
||||||
|
|
||||||
@@ -20,158 +20,78 @@
|
|||||||
<a href="https://buymeacoffee.com/felitendo"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="48"></a>
|
<a href="https://buymeacoffee.com/felitendo"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="48"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## The problem
|
| | Volume after each swipe on AirPods Pro |
|
||||||
|
|---|---|
|
||||||
|
| Before | 6 · 13 · 19 · 25 · 31 · 38 · 44 · 50 ... |
|
||||||
|
| After | 5 · 10 · 15 · 20 · 25 · 30 · 35 · 40 ... |
|
||||||
|
|
||||||
Many Bluetooth devices carry a coarse internal volume grid. AirPods Pro expose
|
## Install
|
||||||
only 16 AVRCP steps, so every swipe on the stem moves the system volume by
|
|
||||||
6.25 %, and the on-screen display walks through
|
|
||||||
|
|
||||||
```
|
|
||||||
6 · 13 · 19 · 25 · 31 · 38 · 44 · 50 · 56 · 63 · 69 · 75 · 81 · 88 · 94 · 100
|
|
||||||
```
|
|
||||||
|
|
||||||
instead of clean multiples of five. A speaker's volume buttons do the same
|
|
||||||
thing with whatever grid that speaker happens to use.
|
|
||||||
|
|
||||||
This is not a desktop misconfiguration. KDE's own volume step is already
|
|
||||||
exactly 5 %. The grid lives in the device firmware, and it cannot be changed:
|
|
||||||
the device sends *absolute* volume values over AVRCP, not increments.
|
|
||||||
|
|
||||||
## What this does
|
|
||||||
|
|
||||||
`bt-volume-step` watches for device-initiated volume changes, takes only their
|
|
||||||
*direction* into account, and applies a clean step of its own instead. One
|
|
||||||
press or swipe on the device becomes one step on your desktop's grid.
|
|
||||||
|
|
||||||
It works because such devices adopt a volume written back over AVRCP silently,
|
|
||||||
without reporting it, so there is no feedback loop. As a side effect the
|
|
||||||
device's internal position follows the corrected value, which keeps it from
|
|
||||||
running into the end of its own scale.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
- PipeWire with `pactl` (`libpulse`)
|
|
||||||
- Python 3.9 or newer
|
|
||||||
- Optional: `kreadconfig6` (KDE Plasma) to follow the desktop's own step size
|
|
||||||
- Optional: `bluez-utils` for device names in `--show`
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
### Arch Linux
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yay -S bt-volume-step
|
yay -S bt-volume-step
|
||||||
```
|
|
||||||
|
|
||||||
### From source
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo make install
|
|
||||||
```
|
|
||||||
|
|
||||||
`make install` honours `PREFIX` and `DESTDIR`; for a per-user install use
|
|
||||||
`make install PREFIX=$HOME/.local`.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Enable it for your user session:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
systemctl --user enable --now bt-volume-step
|
systemctl --user enable --now bt-volume-step
|
||||||
```
|
```
|
||||||
|
|
||||||
That is the whole setup. Connect a Bluetooth device and use its volume
|
Needs PipeWire and Python 3.9 or newer.
|
||||||
control.
|
|
||||||
|
|
||||||
## Calibration
|
## How to use
|
||||||
|
|
||||||
The daemon measures each device's grid on its own. **While a device's grid is
|
Connect your device and press volume up three or four times. Now it knows the device and every
|
||||||
unknown it does not intervene at all**, it only watches. Once the same jump
|
step is clean.
|
||||||
has repeated three times, that jump is accepted as the device step and
|
|
||||||
remembered, and corrections start from then on. In practice: press volume-up
|
|
||||||
three or four times on a new device and it is set up.
|
|
||||||
|
|
||||||
Show what has been measured:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bt-volume-step --show
|
bt-volume-step --show # what it measured
|
||||||
|
bt-volume-step --reset # forget it
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
## More
|
||||||
file: /home/you/.local/state/bt-volume-step/devsteps.json
|
|
||||||
AirPods Pro (30_0E_43_04_52_19) = 6.25 % (16 steps)
|
|
||||||
```
|
|
||||||
|
|
||||||
Discard a measurement (all devices, or one MAC):
|
<details>
|
||||||
|
<summary>How it works</summary>
|
||||||
|
|
||||||
```bash
|
Many Bluetooth devices only know a few volume steps (AirPods Pro: 16), and they send the volume as a
|
||||||
bt-volume-step --reset
|
number, not as "up" or "down". bt-volume-step only looks at which way the volume moved and sets a
|
||||||
bt-volume-step --reset 30_0E_43_04_52_19
|
clean step of its own. The device takes that new volume without a word, so nothing fights back.
|
||||||
```
|
|
||||||
|
|
||||||
To keep the daemon from calibrating itself onto keyboard input, jumps that
|
It only steps in once it has seen the same jump three times. Until then it just watches.
|
||||||
match the desktop's own step size are excluded from measurement, as are jumps
|
|
||||||
below 1.5 % or above 20 %. A device whose grid happens to equal the desktop
|
|
||||||
step therefore never calibrates, and is left alone.
|
|
||||||
|
|
||||||
## Configuration
|
</details>
|
||||||
|
|
||||||
On KDE Plasma the step size comes from *System Settings → Audio → Volume step*
|
<details>
|
||||||
(`plasmaparc [General] VolumeStep`, read through `kreadconfig6` so KDE's
|
<summary>Settings</summary>
|
||||||
configuration cascade applies). Changes take effect within two seconds, with
|
|
||||||
no restart. On other desktops, or without `kreadconfig6`, it falls back to
|
|
||||||
5 %.
|
|
||||||
|
|
||||||
Everything can be overridden through the environment. Put these in a drop-in
|
On KDE Plasma the step comes from *System Settings → Audio → Volume step*, elsewhere it is 5 %.
|
||||||
(`systemctl --user edit bt-volume-step`):
|
To change more, use `systemctl --user edit bt-volume-step`:
|
||||||
|
|
||||||
| Variable | Effect |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `BT_VOL_STEP` | fixed step size in percent; ignores the desktop setting |
|
| `BT_VOL_STEP` | Fixed step in percent |
|
||||||
| `BT_VOL_DEVSTEP` | fixed device grid in percent; skips measurement |
|
| `BT_VOL_DEVSTEP` | Fixed device step, skips measuring |
|
||||||
| `BT_VOL_MAC` | only watch this device (MAC with `_` instead of `:`) |
|
| `BT_VOL_MAC` | Only this device (MAC with `_` instead of `:`) |
|
||||||
| `BT_VOL_MAX` | upper limit in percent (default 100) |
|
| `BT_VOL_MAX` | Highest volume in percent (default 100) |
|
||||||
|
|
||||||
The daemon handles several connected Bluetooth devices at once, keeping state
|
</details>
|
||||||
and calibration per device.
|
|
||||||
|
|
||||||
## Localisation
|
<details>
|
||||||
|
<summary>Limits</summary>
|
||||||
|
|
||||||
Messages follow `LC_ALL` / `LC_MESSAGES` / `LANG`. English and German are
|
- A volume change from somewhere else that happens to match one or two device steps can be read
|
||||||
included; other languages fall back to English. To add one, extend
|
as a swipe.
|
||||||
`TRANSLATIONS` in the script. English strings are the keys.
|
- Devices that report their volume back are not supported. Set a volume and check after a few
|
||||||
|
seconds with `pactl get-sink-volume`: if it moved on its own, this tool is not for that device.
|
||||||
|
|
||||||
## Limitations
|
</details>
|
||||||
|
|
||||||
**Foreign volume changes can be misread.** PipeWire events carry no
|
<details>
|
||||||
information about where a change came from, so a jump that happens to match
|
<summary>Build from source</summary>
|
||||||
one or two device steps is indistinguishable from a button press. The daemon
|
|
||||||
accepts at most two steps per event to keep that window narrow, but it cannot
|
|
||||||
close it entirely.
|
|
||||||
|
|
||||||
**Devices that report their volume back are not supported.** The approach
|
|
||||||
assumes a device accepts a written volume silently. One that echoes a snapped
|
|
||||||
value back would oscillate. To check, set a volume and watch it for a few
|
|
||||||
seconds:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pactl set-sink-volume bluez_output.XX_XX_XX_XX_XX_XX.1 40%
|
|
||||||
sleep 5 && pactl get-sink-volume bluez_output.XX_XX_XX_XX_XX_XX.1
|
|
||||||
```
|
|
||||||
|
|
||||||
If the value drifts on its own, this tool is the wrong approach; disabling
|
|
||||||
hardware volume (`bluez5.enable-hw-volume = false` in WirePlumber) is the
|
|
||||||
alternative, at the cost of the device's own control.
|
|
||||||
|
|
||||||
## Tests
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
sudo make install
|
||||||
make check
|
make check
|
||||||
```
|
```
|
||||||
|
|
||||||
Covers the decision logic and the measurement, including simulated devices
|
`make install PREFIX=$HOME/.local` works without root.
|
||||||
with 8, 16 and 32 steps.
|
|
||||||
|
|
||||||
## License
|
</details>
|
||||||
|
|
||||||
BSD 3-Clause. See [LICENSE](LICENSE).
|
BSD 3-Clause.
|
||||||
Reference in new issue
Block a user