- Mon 09 January 2023
- Audio
- #linux, #audio, #networking, #pipewire, #alsa, #sound, #terminal, #command-line
Are you a nerd like me?
Do you want to connect audio devices in a Linux system easily, programmatically, and with a little help from Python?
Ok, so you're probably not quite a nerd like me, but if you'd probably still find some value from hearing about this cool sub-system in the Pipewire ecosystem.
Pipewire composes ports on devices to provide a mechanism to make connections between outputs (sources) and inputs
(sinks). This makes it possible to connect applications and interfaces into any arbitrary connection set. There are even
great tools like qpwgraph
which make it possible to connect these
interface graphically, and make it all smooth and beautiful.
That graphical application is beautiful, but what if you want to make those connections a little more manually, or (if you're like me), programmatically. Well, good news! Pipewire offers a whole system to make those connections from the command-line.
Enter pw-link
$> pw-link --help
pw-link : PipeWire port and link manager.
Generic: pw-link [options]
-h, --help Show this help
--version Show version
-r, --remote=NAME Remote daemon name
List: pw-link [options] [out-pattern] [in-pattern]
-o, --output List output ports
-i, --input List input ports
-l, --links List links
-m, --monitor Monitor links and ports
-I, --id List IDs
-v, --verbose Verbose port properties
Connect: pw-link [options] output input
-L, --linger Linger (default, unless -m is used)
-P, --passive Passive link
-p, --props=PROPS Properties as JSON object
Disconnect: pw-link -d [options] output input
pw-link -d [options] link-id
-d, --disconnect Disconnect ports
That's what the interface of the PW-Link command-line tool looks like. Simple, powerful, and GREAT.
Want to list the sources (outputs)?
$> pw-link --output --id
36 Midi-Bridge:Midi Through:(capture_0) Midi Through Port-0
43 v4l2_input.pci-0000_03_00.4-usb-0_4_1.0:out_0
47 alsa_output.pci-0000_03_00.6.analog-stereo:monitor_FL
49 alsa_output.pci-0000_03_00.6.analog-stereo:monitor_FR
50 alsa_input.pci-0000_03_00.6.analog-stereo:capture_FL
51 alsa_input.pci-0000_03_00.6.analog-stereo:capture_FR
Or... how about the sinks (inputs)?
$> pw-link --input --id
35 Midi-Bridge:Midi Through:(playback_0) Midi Through Port-0
46 alsa_output.pci-0000_03_00.6.analog-stereo:playback_FL
48 alsa_output.pci-0000_03_00.6.analog-stereo:playback_FR
Marvelous, isn't it?
But how about getting those links created? How's it done? Can it be done programmatically? With Python?
Heh.
Well, now it can!
Enter pipewire_python
pipewire_python
is the core grounds of a Python Pipewire wrapper. It was
created by Pablo Diaz and offers some great functionality with Pipewire wrapped up in
Python. Unfortunately, it didn't yet have pw-link
functionality to list, create, and modify links in Pipewire. That
said, I've been able to add some of the functionality. It's in-progress in a
pull-request.
The PR is only a draft at the time of this writing, however, I'm hopeful it will be something that I can open officially
within a few days, and will be able to merge before the end of the week. When it does merge, pipewire_python
will
have functional support to list inputs, outputs, and links, and it will be able to create links as mono (single
channel) or automatic-stereo (automated Left/Right channel pairing) connections. It'll be simple!
from pipewire_python import link
inputs = link.list_inputs()
outputs = link.list_outputs()
# Connect the last output to the last input -- during testing it was found that
# Midi channel is normally listed first, so this avoids that.
source = outputs[-1]
sink = inputs[-1]
source.connect(sink)
# Fun Fact! You can connect/disconnect in either order!
sink.disconnect(source) # Tada!
# Default Input/Output links will be made with left-left and right-right
# connections; in other words, a straight stereo connection.
# It's possible to manually cross the lines, however!
source.right.connect(sink.left)
source.left.connect(sink.right)
Won't that be slick?
Needless to say, I'm very excited. I'm going to use this for an automated system designed to support a VBAN streaming network built fully on Linux. It'll be a robust, low-latency audio streaming system for my home, and I won't have to use the "dreaded Microsoft Windows". Won't that be neat?
Stay tuned... I'll be sharing more on this project soon!