TL;DR: The Mackie ProFX works nicely as a Linux desktop sound card. To make it more useful, there is a trick to split the audio into two stereo outputs, instead of using it as a bare 4 channel audio output.
I use a Mackie ProFX mixer as the audio interface on my desktop. It is not a complicated studio setup. I want normal desktop audio, reliable headphones, and speakers that can be controlled separately without having to remember which physical USB channel pair does what. In addition to that, I have a separate PC with a Traktor DJ controller that uses the mixer as it’s output. Everything connects to a pair of KRK Rokit 5 speakers.
The issue with using this mixer on my desktop PC, is Linux detects the sound card as a single 4-channel output instead of separating them as 2 2-channel outputs. The Windows drivers support this by default. In Linux, we of course have to do a bit more tinkering.
The Mackie ProFX mixer provides the USB audio interface and the physical controls.
The mixer shows up as a USB audio device with four output channels. That is technically correct, but not intiutive enough for me to easily switch between. I do not want every application to know about front-left, front-right, rear-left, and rear-right. I want applications to see a normal headphone output and a normal speaker output.
PipeWire makes that easy with two loopback devices.
The PipeWire split
The relevant config lives in ~/.config/pipewire/pipewire.conf.d/10-split-channels.conf:
context.modules = [
# Create a virtual stereo output that desktop applications can choose.
{ name = libpipewire-module-loopback
args = {
node.description = "Headphones"
# This is the visible sink shown in pavucontrol.
capture.props = {
# Keep volume controls ready before the first playback stream.
node.always-process = true
state.restore-props = true
node.name = "headphones_virtual"
media.class = "Audio/Sink"
audio.position = [ FL FR ]
device.icon-name = "audio-headphones"
}
# This hidden stream forwards the virtual sink to the real Mackie channels.
playback.props = {
node.name = "headphones_real_link"
media.class = "Stream/Output/Audio/Internal"
node.hidden = true
target.object = "alsa_output.usb-LOUD_Technologies_Inc._ProFX-00.analog-surround-40"
audio.position = [ FL FR ]
# Wait for the Mackie instead of disappearing or choosing another sink.
node.dont-reconnect = false
node.dont-fallback = true
node.linger = true
stream.dont-remix = true
node.passive = true
}
}
}
# Create another virtual stereo output for the speaker channel pair.
{ name = libpipewire-module-loopback
args = {
node.description = "Speakers"
# This is the second visible sink shown in pavucontrol.
capture.props = {
# Keep volume controls ready before the first playback stream.
node.always-process = true
state.restore-props = true
node.name = "speakers_virtual"
media.class = "Audio/Sink"
audio.position = [ FL FR ]
device.icon-name = "audio-speakers"
}
# This hidden stream forwards audio to the rear channel pair on the Mackie.
playback.props = {
node.name = "speakers_real_link"
media.class = "Stream/Output/Audio/Internal"
node.hidden = true
target.object = "alsa_output.usb-LOUD_Technologies_Inc._ProFX-00.analog-surround-40"
audio.position = [ RL RR ]
# Wait for the Mackie instead of disappearing or choosing another sink.
node.dont-reconnect = false
node.dont-fallback = true
node.linger = true
stream.dont-remix = true
node.passive = true
}
}
}
]
The first loopback creates a virtual stereo sink called Headphones and sends it to the front-left/front-right channels on the Mackie device. The second creates Speakers and sends it to rear-left/rear-right.
The important part is that both virtual sinks look like ordinary stereo outputs to desktop applications. The config makes sure to route them to the correct outputs on the sound card.
Really nice output selection list: Headphones and Speakers. Nothing else.
Update: surviving login and remembering volume
23 October 2026: The original configuration had two annoying habits: after the first login following a boot, only Headphones was selectable until I restarted PipeWire, and volume would often return to 100%. The settings in the example above solve both issues. No login script or automatic service restart is involved.
This configuration is for Debian 13 with PipeWire 1.4.2 and WirePlumber 0.5.8. Keep your own backend name in target.object; the one above is specific to my Mackie and its four-channel profile.
The playback side needs three settings together:
node.dont-reconnect = falseallows the stream to reconnect when the backend returns.node.dont-fallback = trueprevents it from choosing another output while the Mackie is missing.node.linger = truetells WirePlumber to wait when that specific target is unavailable, rather than destroy the stream. Without this, disabling fallback can make a missing target take the virtual output with it.
stream.dont-remix = true keeps the requested channel layout intact: Headphones links to FL/FR and Speakers to RL/RR. The PipeWire loopback documentation has a similar rear-channel example.
For volume, the important change in this setup was node.always-process = true on each visible sink. Without it, volume adjustments on an unused output could fail to stick, and volume could reset to 100%. Keeping the virtual sinks processing lets volume changes take effect before playback starts and allows WirePlumber to restore the previous levels after a restart. state.restore-props = true explicitly keeps native state restoration enabled; it was already enabled by default. See the PipeWire property reference for the scheduling and state settings. Keeping virtual nodes processing can increase idle audio processing, so this is a deliberate tradeoff for this desktop setup.
Apply the revised configuration with systemctl --user restart pipewire.service. The restart briefly interrupts audio.
Stable sample rate
There is one more small config file, ~/.config/pipewire/pipewire.conf.d/50-rate.conf:
context.properties = {
default.clock.rate = 48000
default.clock.allowed-rates = [ 48000 ]
default.clock.quantum = 1024
default.clock.max-quantum = 2048
}
This keeps the graph at 48 kHz and uses a conservative quantum. This is a conservative setting, best suitable for a normal desktop and gaming environment. Lower latency and higher clock rate is definitely possible but I noticed some issues where I had to restart the pipewire service to get my sound back to normal when doing so.