Showing posts with label sound. Show all posts
Showing posts with label sound. Show all posts

Saturday, March 31, 2012

Pulseaudio: USB sound device hotplug

When using Pulseaudio and pavucontrol, one can easily change the default sound device by clicking the fallback button on the device. However, this assumes that the default device is always connected.
When a USB sound device, for example a headset, is set as fallback and then disconnected, the fallback device becomes the PCI sound device, or whatever device is still connected. This happens both for source and sink configuration.

It is possible to solve the problem by creating a udev rule.
What needs to be done:
- Use udev to identify the USB sound device plugging in.
- Run pacmd to set default source & sink as the current user.

In this example, I used a Speedlink Medusa 5.1 USB headset, which is configured in pulseaudio as "Analog Surround 5.1 Output & Analog Stereo Input". The system I'm using therefore has these devices:

1. Intel HD Audio
2. USB sound device

Using aplay -l displays the following:
[stavros@stavros-laptop ~]$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Intel [HDA Intel], device 0: ALC889 Analog [ALC889 Analog]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
card 0: Intel [HDA Intel], device 1: ALC889 Digital [ALC889 Digital]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: Intel [HDA Intel], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: Device [USB Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
As you can see, the internal sound card is listed as card 0, and the USB device I want to set as default is listed as card 1.
Since I won't be plugging in any other sound device, I can use "card1" in a udev rule.

udevadm shows events that can be used to create rules for:
[stavros@stavros-laptop ~]$ udevadm monitor --kernel --subsystem=sound
monitor will print the received events for:
KERNEL - the kernel uevent

KERNEL[2215.105651] add      /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1:1.0/sound/card1 (sound)
KERNEL[2215.105732] add      /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1:1.0/sound/card1/pcmC1D0p (sound)
KERNEL[2215.105824] add      /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1:1.0/sound/card1/pcmC1D0c (sound)
KERNEL[2215.106001] add      /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1:1.0/sound/card1/controlC1 (sound)
KERNEL[2215.190918] change   /devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1:1.0/sound/card1 (sound)

The device was not completely initialised when the "add" event fired, so I used the "change" event at the end, and created the following rule in /etc/udev/rules.d:

/etc/udev/rules.d/60-snd-usb.rules
SUBSYSTEM=="sound", KERNEL=="card1", ACTION=="change", RUN+="/home/stavros/bin/pulse-ins.sh"

This rule will execute /home/stavros/bin/pulse-ins.sh when card1 is inserted.
One script alone would not work, so I used 2, with pulse-ins.sh merely executing the other script

/home/stavros/bin/pulse-ins.sh:
#!/bin/bash
su -c "/home/stavros/bin/pulse_insert_card.sh & exit" stavros
This script is executed by udev, and it runs another script as the current user, since pacmd has to be run as a regular user.

/home/stavros/bin/pulse_insert_card.sh:
#!/bin/bash
/usr/bin/pacmd set-default-sink alsa_output.usb-0d8c_USB_Sound_Device-00-Device.analog-surround-51
/usr/bin/pacmd set-default-source alsa_input.usb-0d8c_USB_Sound_Device-00-Device.analog-stereo
This runs pacmd and sets the default source & sink devices.

Then, the following command reloads the udev rules without having to reboot. It must be run as root:
[root@stavros-laptop stavros]# udevadm control --reload-rules

Now, the USB sound device will be set as fallback when plugged in, and the internal device will be used as fallback when it is disconnected.