Prototype of automatic backend-switching for JACK2 using dbus.
You may know this Mac/OSX feature: one plugs or unplugs an external audio-interfaces and the system automatically switches the sound to the new device. - It may not always be what you want, but it is an very handy feature especially for mobile systems. and here's how to set this up for JACK on GNU/Linux..
First, we need a mechanism to switch the “JACK backend” in order to switch between audio-interfaces. The task includes taking care of re-connecting physical I/O ports in case they're different on each device.
Second, said mechanism needs to be triggered automatically when a new device is connected or if a device goes away.
Here's a short annotated demo-video:
(well yes, I should have ripped out that USB cord more visibly.. sorry, next time. I might use a real camera too, then.)
dbus-triggerd and a
jack2 debian packages (source and i386) are available from
deb http://rg42.org/deb/ sid main
patch, compile and install (or get the debian package).
compile and install
dbus-triggerd (or get the debian package).
download and install
myjackctl.sh to PATH (
open a window to watch
tail -f ~/.log/jack/jackdbus.log
killall -9 jackd jackdbus # clean start
jack_control eps verbose true # tell jackdbus to be verbose
myjackctl.sh alsa hw:0 1024 48000 3 # launch jackd on first ALSA interface -p1024 -r48000 -n3
myjackctl.sh alsa hw:1 # switch to second ALSA interface
Launch some jack clients, players etc and repeat testing with
dbus-triggerd is a tool to trigger shell-commands upon receiving a given dbus-signal.
It can be used to invoke
myjackctl.sh in order to change the JACK-backend if
a new audio-interface is connected (system-dbus
org.freedesktop.Hal.Manager,member=DeviceAdded) → use the newly connected device.
an audio-interface is disconnected (system-dbus
org.freedesktop.Hal.Manager,member=DeviceRemoved) → switch to a fallback audio-interface.
JACK daemon signals device-error (session-dbus
org.jackaudio.JackControl,member=DeviceError) → switch to a fallback audio-interface.
The two last are redundant and exclusive. JACKd still needs a patch to send a
DeviceError. Using HAL's
DeviceRemoved may be problematic for setups with more than two sound-cards if the removed device was not currently the one used by JACK.
Example to launch
make || exit
### switch to sound 'hw:0' on any DeviceError
# This requires a patched JACK2, that sends a DeviceError
./dbus-triggerd $@ "type='signal',path=/org/jackaudio/Controller,interface=org.jackaudio.JackControl,member=DeviceError" --shell "myjackctl.sh alsa hw:0" &
# This an alternative to the above, using the HAL message
#dbus-triggerd $@ --system "type='signal',path=/org/freedesktop/Hal/Manager,interface=org.freedesktop.Hal.Manager,member=DeviceRemoved,arg0=/org/freedesktop/Hal/devices/usb_device_582_74_noserial_if0_sound_card_2" --shell "myjackctl.sh alsa hw:0" &
### switch to external USB sound device 'hw:2' when it's connected
./dbus-triggerd $@ --system "type='signal',path=/org/freedesktop/Hal/Manager,interface=org.freedesktop.Hal.Manager,member=DeviceAdded,arg0=/org/freedesktop/Hal/devices/usb_device_582_74_noserial_if0_sound_card_2" --shell "myjackctl.sh alsa hw:2" &
Here be dragons…
The mechanism for backend-switching is implemented by a shell-script
myjackctl.sh (which call
dbus-send) that controls jack2d by exchanging dbus-messages.
myjackctl.sh is started with different command-line parameters on-demand by
org.jackaudio.JackControl,member=DeviceError (requires patch to jack2)
myjackctl.sh uses the
org.jackaudio.PatchBay dbus-API which is broken in jack2-r4120 (see ticket below) and fixed by Nedko in jack2-r4366.
Future: Instead of patching jack2 to send additional messages (here:
org.jackaudio.JackControl,member=DeviceError), the trigger functionality should be built into jackd, but requires a callback to the control API to be added to JACK.
The shell hook-script (myjackctl.sh) could be implemented easier and more flexible using python (jack-control API bindings) or similar language more suitable to parse and provide audio-port mapping and configuration.