Configuring Deckboard I figure Pipewire IDs can change on reboot or suspend.
Motivation
I got an idea, and I picked an old Amazon Fire tablet 8 to use it as "StreamDeck" . I was configuring Deckboard, to use it for many things; one of them is to switch between audio devices. I’m running NixOS and Pipewire as sound server.
Changing default device
Let’s take a look at the basic usage of WirePlumber CLI:
- $ wpctl
- Usage:
- wpctl [OPTION…] COMMAND [COMMAND_OPTIONS] - WirePlumber Control CLI
- Commands:
- status
- get-volume ID
- inspect ID
- set-default ID
- set-volume ID VOL[%][-/+]
- set-mute ID 1|0|toggle
- set-profile ID INDEX
- clear-default [ID]
- Help Options:
- -h, --help Show help options
- Pass -h after a command to see command-specific options
My use case is using the command set-default
to change a default device, but we need to figure out the ID.
To get the ID we have to use status
, status will throw a lot of information, but we need to focus in Audio > Sinks
- $ wpctl status
- [...]
- Audio
- ├─ Devices:
- │ 46. Renoir Radeon High Definition Audio Controller [alsa]
- │ 48. Family 17h/19h HD Audio Controller [alsa]
- │ 80. Ditoo-audio [bluez5]
- │ 132. GSP 370 [alsa]
- │
- ├─ Sinks:
- │ * 58. Family 17h/19h HD Audio Controller Analog Stereo [vol: 0.50]
- │ 68. Renoir Radeon High Definition Audio Controller Digital Stereo (HDMI) [vol: 0.40]
- │ 81. Ditoo-audio [vol: 0.70]
- │ 103. GSP 370 Analog Stereo [vol: 0.55]
- [...]
Current default is mark with the asterisk *
, using those IDs you can set the default device,
for example, I want to set default device to GSP 370:
The problem: Dynamic IDs
After a reboot or suspend IDs can potentially change, to avoid it we will parse the wpctl status
output to know
exactly which number is needed to set the desired device as default.
Because names can change for many reasons, I prefer to use status with --names
, it will list sink with internal names
and that remove the chance to have two equal names.
- $ wpctl status --name
- [...]
- Audio
- ├─ Devices:
- │ 46. alsa_card.pci-0000_06_00.1 [alsa]
- │ 48. alsa_card.pci-0000_06_00.6 [alsa]
- │ 80. bluez_card.XX_XX_XX_XX_XX_XX [bluez5]
- │ 132. alsa_card.usb-Sennheiser_GSP_370-00 [alsa]
- │
- ├─ Sinks:
- │ * 58. alsa_output.pci-0000_06_00.6.analog-stereo [vol: 0.50]
- │ 68. alsa_output.pci-0000_06_00.1.hdmi-stereo [vol: 0.40]
- │ 81. bluez_output.XX_XX_XX_XX_XX_XX.1 [vol: 0.70]
- │ 103. alsa_output.usb-Sennheiser_GSP_370-00.analog-stereo [vol: 0.55]
- [...]
Given this list I need the switch between 58
and 103
, but we will get those numbers via regex. There is plenty of ways
to do this, my preference is the command sed
.
Obtaining the value
Let me show you separated commands, with a brief explanation.
1. Status
wpctl status --name
This will list the current audio sinks, similar to what I show early.
2. Grep
Using the output of the previous command, execute grep filtering with sinkname
.
grep 'sinkname'
For example sinkname
could be:
grep 'alsa_output.pci-0000_06_00.6.analog-stereo'
This command will return the exact line where the needed value is:
│ 58. alsa_output.pci-0000_06_00.6.analog-stereo [vol: 0.50]
3. Sed
Using the output of the previous command, I use sed
to extract the needed value. This command has this
basic structure s/<input>/<output>/
. The command to execute is sed 's/^[^0-9]*\([0-9]\+\)\..*/\1/'
,
let’s break it down:
- Start searching from the beginning
^
. - Any character
[^0-9]*
but numbers. Asterisk*
means 0 or more occurrences. In this case^
is negation. - Capture is
()
, everything inside parenthesis is captured y and the captured text is used in output section of the command with\1
, parenthesis needs to be escaped\(\)
. - Inside capture look for numbers
[0-9]+
, plus sign+
means one or more occurrences followed by a point\.
escaped. - The rest of the line does not matter, already we got what we need, then at the end of the pattern add
.*
it means any character zero or more occurrences. - And the last thing is use the capture value in the output side of the command
\1
.
Putting command all together
wpctl set-default $(echo "$(wpctl status --name | grep 'alsa_output.pci-0000_06_00.6.analog-stereo')" | sed 's/^[^0-9]*\([0-9]\+\)\..*/\1/')
wpctl set-default $(echo "$(wpctl status --name | grep 'alsa_output.usb-Sennheiser_GSP_370-00.analog-stereo')" | sed 's/^[^0-9]*\([0-9]\+\)\..*/\1/')
You need to adapt the grep
device value to fit your needs.
Thanks for reading!
Namaste.