Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

Pulseaudio: remap source when usb audio interface is connected

Writer Andrew Mclaughlin

I have Roland UA-22 (Duo Capture Ex) USB audio interface, and by default it presents its two input channels as a single stereo source. However, I want to use them separately as independent sources.

Using this advice I added the following two lines to /etc/pulse/default.pa to create virtual sources:

load-module module-remap-source source_name=UA_22_Input_1 source_properties="device.description='Roland UA-22 Input 1'" master=alsa_input.usb-Roland_UA-22-00.analog-stereo master_channel_map=front-left,front-left channel_map=front-left,front-right
load-module module-remap-source source_name=UA_22_Input_2 source_properties="device.description='Roland UA-22 Input 2'" master=alsa_input.usb-Roland_UA-22-00.analog-stereo master_channel_map=front-right,front-right channel_map=front-left,front-right

This works fine after I restart pusleaudio when I'm fully booted up with pulseaudio -k. However, when I boot (with the device connected), or when I unplug and replug the device, the virtual sources disappear and don't get recreated until I kill pulseaudio again.

I suspect that what's happening here is that at boot time the sound card is not fully utilized by the time pulseaudio evaluates its config, and it doesn't re-evaluate it when the interface is connected later.

Is there a way to make pulseaudio restore the sources automatically when I connect my audio interface without killing the whole thing?

1 Answer

I'm not sure if this would help on boot, but for disconnecting & reconnecting you can try to use udev. I do this for my MOTU M2, but presumably it could be tweaked for your device. First find out what udev knows about your device. Run udevadm monitor in a terminal and connect your device. You should see a line like:

KERNEL[425578.748455] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.6 (usb)

(followed by many others)

Copy the /devices/ path and run:

$ udevadm info -ap /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.6 looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.6': ... ATTR{product}=="M2" ATTR{manufacturer}=="MOTU" ...

Now create a .rules file in /etc/udev/rules.d/, (you could call yours 99-roland.rules or something).

--- /etc/udev/rules.d/99-motu.rules ---

ACTION=="add", ATTR{manufacturer}=="MOTU", ATTR{product}=="M2", RUN+="/home/marf/self/bin/motu-udev.sh"

Obviously you'll need to change the ATTR parameters to match what you found out with udevadm info and the script location to match where you want to put the next script.

Tell udev to load the new rules:

sudo udevadm control --reload-rules

In the script pointed to by the RUN parameter, you can run pactl commands to setup pulseaudio how you want for when your device is connected. (If you also need to do things on disconnect, you could use ACTION="remove" in the udev config and point to a different script if desired.)

For my device, unfortunately it doesn't show up in pulseaudio until after udev finishes, so I have to spawn a separate script and wait for it to show up. I'm not sure if this is specific to my device, or if it's just because pulseaudio is also using udev to add the device. Also, the scripts from udev run as root, but pulseaudio is usually running as your unprivileged user account. The first few lines are to figure out what that account is (this part I found in the Arch wiki). Here are my scripts:

--- motu-udev.sh ---

#! /bin/bash
export PATH=/usr/bin:/bin
USER_NAME=$(who | awk -v vt=tty$(fgconsole) '$0 ~ vt {print $1}')
USER_ID=$(id -u "$USER_NAME")
PULSE_SERVER="unix:/run/user/"$USER_ID"/pulse/native"
/home/marf/self/bin/motu-pulse.sh "$USER_NAME" "$PULSE_SERVER" & disown

--- motu-pulse.sh ---

#! /bin/sh
USER_NAME="$1"
PULSE_SERVER="$2"
sleep 2
if ! sudo -u "$USER_NAME" pactl --server "$PULSE_SERVER" list modules | grep master=alsa_input.usb-MOTU > /dev/null; then sudo -u "$USER_NAME" pactl --server "$PULSE_SERVER" load-module module-remap-source master=alsa_input.usb-MOTU_M2_M2MT078C8F-00.analog-stereo master_channel_map=front-left channel_map=mono source_name=MXL-M2 source_properties=device.description=MXL-M2
fi
sudo -u "$USER_NAME" pactl --server "$PULSE_SERVER" set-default-sink alsa_output.usb-MOTU_M2_M2MT078C8F-00.analog-stereo

So udev triggers on the device's USB connect, and runs motu-udev.sh. Then motu-udev.sh spawns motu-pulse.sh and disowns it so udev can finish processing (and actually create my device in pulseaudio). The motu-pulse.sh script sleeps for a bit to wait for that to finish, and then it creates the channel mapping if necessary, and sets the device as the default output. (If you only want to use it as an input device, you can leave out the last line)

Some resources I found helpful were the Arch wiki and this tutorial:

Let me know if you find any useful changes, or if there's a way to do this purely in Pulseaudio without udev!

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy