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.)
myjackctl.shmyjackctl - or similar program to switch JACK-backends.
dbus-triggerd- or a similar tool that runs a hook-script on receiving dbus-signals.
dbus-triggerd and a
jack2 debian packages (source and i386) are available from
deb http://rg42.org/deb/ sid main
dbus-triggerd(or get the debian package).
myjackctl.shto PATH (
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
org.freedesktop.Hal.Manager,member=DeviceAdded) → use the newly connected device.
org.freedesktop.Hal.Manager,member=DeviceRemoved) → switch to a fallback audio-interface.
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
#!/bin/sh make || exit killall dbus-triggerd ### 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.