Jackd+A2J with Systemd startup

Optimize your system for ultimate performance.

Moderators: MattKingUSA, khz

Post Reply
mtlwstlk
Established Member
Posts: 5
Joined: Tue Aug 20, 2019 8:06 pm

Jackd+A2J with Systemd startup

Post by mtlwstlk »

I finally managed to get a working startup with systemd.

The setup:
1 alsa card
Load pulseaudio , followed by JackdBus+A2jDbus
(for those who are familiar there's "a2jmidid -e" which doesn't run in dbus mode)

The Pros:
- You can start JackdBus on and off without conflicting with Pulseaudio

The Cons:
- None! :stuck_out_tongue:

The problem with pulseaudio's module of jackdbus, is more often than not it doesn't do its job properly.

With a little tuning of a pre and after of running jackdbus, Systemd allows its unit files to include "ExecStartPre" << which allows one to do things before Jackd tries to grab the Alsa device.

My previous tweaks in getting this setup to work went around to using the "null sink" device with Pulseaudio.

However just recently I found a much better and assuring way that that wasn't enough for PulseAudio to letting go of the alsa card fully. Despite having module-jackdbus-detect always loaded with pulseaudio, sometimes its default sink (when manually starting jackdbus), would not switch to "jack_out" as the pulseaudio's jackdbus is designed to do. It maps and detects jackdbus, and immediately makes the sinks available(so pulseaudio's jackdbus module works half-way), but it sometimes fails to set the sink to jack_out.

My instruction below here, overcomes this problem, and instead uses direct pacmd commands in a dbus-org.jackaudio.service systemd unit file.

The nice thing about it is pulseaudio always gets its sink to jack_out.

The systemd unit file goes into ~/.config/systemd/user (if this path doesn't exist, the user needs to manually create it)
dbus-org.jackaudio.service
"
[Unit]
Description=JACK 2
After=pulseaudio.service
Requires=dbus.socket
Requires=pulseaudio.service

[Service]
Type=dbus
BusName=org.jackaudio.service

ExecStartPre=-/usr/bin/killall -9 jackdbus
ExecStartPre=-/bin/sleep 2
#ExecStartPre=-/usr/bin/pacmd load-module module-null-sink
#ExecStartPre=-/bin/sleep 2
ExecStartPre=-/usr/bin/pacmd set-default-sink null

ExecStartPre=-/usr/bin/pacmd unload-module module-jackdbus-detect
ExecStartPre=-/bin/sleep 1
ExecStartPre=-/usr/bin/pacmd unload-module module-jack-sink
ExecStartPre=-/usr/bin/pacmd unload-module module-jack-source
ExecStartPre=-/bin/sleep 2

ExecStartPre=-/usr/bin/pacmd suspend 1
ExecStartPre=-/bin/sleep 1

ExecStart=/usr/bin/jackdbus auto

ExecStartPost=-/bin/sleep 6
ExecStartPost=/usr/bin/jack_control ds alsa
ExecStartPost=/usr/bin/jack_control dps device hw:NVidia,7
ExecStartPost=/usr/bin/jack_control dps period 512
ExecStartPost=/usr/bin/jack_control dps nperiods 3
ExecStartPost=/usr/bin/jack_control dps rate 48000
ExecStartPost=/usr/bin/jack_control dps input-latency 32
ExecStartPost=/usr/bin/jack_control dps output-latency 32
ExecStartPost=/usr/bin/jack_control dps midi-driver none
ExecStartPost=/usr/bin/jack_control eps driver alsa
ExecStartPost=/usr/bin/jack_control eps realtime True
ExecStartPost=/usr/bin/jack_control eps realtime-priority 95
ExecStartPost=-/bin/sleep 1

ExecStartPost=-/usr/bin/jack_control start
ExecStartPost=-/bin/sleep 3

ExecStartPost=-/usr/bin/pacmd load-module module-jackdbus-detect channels=2 connect=true
ExecStartPost=-/bin/sleep 3
ExecStartPost=-/usr/bin/pacmd set-default-sink jack_out
ExecStartPost=-/usr/bin/pacmd suspend-sink jack_out 0

ExecStop=-/usr/bin/jack_control exit
ExecStopPost=-/bin/sleep 2
ExecStopPost=-/usr/bin/killall -9 jackdbus
ExecStopPost=-/bin/sleep 1

ExecStopPost=-/usr/bin/pacmd unload-module module-jackdbus-detect
ExecStopPost=-/bin/sleep 1
ExecStopPost=-/usr/bin/pacmd unload-module module-jack-sink
ExecStopPost=-/usr/bin/pacmd unload-module module-jack-source
ExecStopPost=-/bin/sleep 1
ExecStopPost=-/usr/bin/pacmd set-default-sink alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1
ExecStopPost=-/bin/sleep 2
ExecStopPost=-/usr/bin/pacmd suspend 0

SuccessExitStatus=0
RemainAfterExit=yes

[Install]
WantedBy=default.target
"

dbus-org.gna.home.a2jmidid.service
"
[Unit]
Description=alsa2jack dbus
Requires=dbus.socket
Requires=dbus-org.jackaudio.service
After=dbus-org.jackaudio.service

[Service]
Type=dbus
BusName=org.gna.home.a2jmidid

ExecStartPre=-/usr/bin/killall -9 a2jmidid
ExecStartPre=-/bin/sleep 2

ExecStart=/usr/bin/a2jmidid dbus
ExecStartPost=/bin/sleep 3
ExecStartPost=/usr/bin/a2j_control ehw
ExecStartPost=/bin/sleep 5
ExecStartPost=/usr/bin/a2j_control start

ExecStop=/usr/bin/a2j_control exit
ExecStopPost=-/bin/sleep 2
ExecStopPost=-/usr/bin/killall -9 a2jmidid

SuccessExitStatus=0
RemainAfterExit=true

[Install]
WantedBy=default.target
"

---
these dbus files also need to be changed
(If your distro is using a slightly different name in /usr/share/dbus-1/services, then you need to use that filename in ~/.local/share/dbus-1/services )

~/.local/share/dbus-1/services/org.jackaudio.service
"
[D-BUS Service]
Name=org.jackaudio.service
#Exec=/usr/bin/jackdbus auto

SystemdService=dbus-org.jackaudio.service
"

---
for dbus unit file org.gna.home.a2jmidid.service
in ~/.local/share/dbus-1/services/ ,
"
[D-BUS Service]
Name=org.gna.home.a2jmidid
#Exec=/usr/bin/a2jmidid dbus

SystemdService=dbus-org.gna.home.a2jmidid.service
"
---

To prepare these units for auto-startup,

systemctl --user reenable dbus-org.gna.home.a2jmidid.service
systemctl --user reenable dbus-org.jackaudio.service
systemctl --user daemon-reload

The daemon-reload statement may be redundant but isn't harmful. The "systemctl --user enable __ " statement doesn't fully create the appropriate symlinks for the .wants folder, that's why you would need to use "reenable" to ensure the correct symlinks are created under the user's systemd sub-folders in ~/.config/systemd/user/.

The "reenable" and daemon-reload statements are not enough to ensure that the unit files are stored in .wants folders, you can verify this by using,
systemctl --user list-dependencies default.target

If a user wants to alter the auto-start behaviour of these two service units in ~/.config/systemd/user, they can use
systemctl --user disable dbus-org.gna.home.a2jmidid
systemctl --user disable dbus-org.jackaudio

to start up manually, one can just do
systemctl --user start dbus-org.gna.home.a2jmidid.service
and that should start up the jackaudio service along with it.

The lines with dp, dps and eps in jack.service can be removed if a user wants to use other tools to store jackdbus settings.

Since I don't trust ~/.config/jack/conf.xml as it could get overwritten by other tools, << this configuration file is where the runtime jackdbus stores it settings.
The thing is jackdbus can be called from different tools. If you're like me and like to try different jack tools but do not want to worry about your settings getting lost, you can always stick with "qjackctl" or you can ammend jack_control statements in the dbus-org.jackaudio.service file as demonstrated.

For checking what settings are taking place with jackdbus,
"jack_control ep" and "jack_control dp" can be used to show the runtime jackdbus settings..

To verify that pulseaudio is indeed pointing to jack_out,

pacmd list-sinks, and look for "*" on the index/name where it says "<jack_out>"

The "pacmd suspend __" takes a 0 or 1 , and works well enough that the null sink module does not need to be used, but I take just an extra step of precaution as the null sink has worked well for me in the past. The pacmd suspend adds even better assurance pulseaudio and jackd won't fight for the alsa device..

While jackdbus is running, "pacmd suspend-sink jack_out 0" makes it possible to output to only jack_out with pulseaudio.. If another sink needs to be used, a command similar to it can be used, but do not use the alsa device that jackdbus wants to grab onto.

For users who have this systemd file on their linux setup,
/usr/lib/systemd/user/pulseaudio.service

and you do not have "--realtime" applied to the pulseaudio command, you can modify it after copying it to your user's path of systemd.

cd ~/.config/systemd/user
cp /usr/lib/systemd/user/pulseaudio.service .

and edit the line containing ExecStart=
eg,
from "ExecStart=/usr/bin/pulseaudio --daemonize=no" from the system's default
to something similar to
"ExecStart=/usr/bin/pulseaudio --daemonize=no --realtime --no-cpu-limit"

If you use jackdbus, don't use jackd. That's the easiest way to go about it..

If you do use jackd, then make sure you do the same check, suspend pulseaudio's sinks, etc.. and it should work the same..

For those who use jackd:
-> the command for a2jmidid with hardware-redirected ports is -> "a2jmidid -e"

A user would notice that I use "jack_control exit" and "a2j_control exit". The reason why I use this is because "jack_control stop" and "a2j_control stop" do not work perfectly sometimes when their dbus activation is still on.

Issuing start/stop with jack_control and/or a2j_control does not always work and so the only way for the two to cooperate again is to bring down the dbus activation and then later reactivate.

It's flakey, so it's best to do a full kill switch on both and that always solves it.

It's a little instructive, but basically you are making just four files and not changing anything outside the user home folder.

good luck peeps


[
The above notes covers the setup of compliant jack-midi applications.

Bitwig(I'm a user of) needs a workaround since it is non-jackmidi compliant and always wants to grab the alsamidi device:
a user cannot have a2jmidid loaded, and so if you are using systemd and have followed the provided instructions, you can simply turn on and off a2j on the fly at any given moment in order for bitwig to see and use midi devices appropriately.

-> systemctl --user disable a2j.service ; disables the on-boot for a2j
-> systemctl --user stop a2j.service ; shuts down the current running a2j service

For non-systemd/dbus things, ensure you are not loading "a2jmidid -e" (in its non-dbus form)

For users who use jackd --> Make sure ~/.jackdrc or your startup Qjactkctl settings does not use Jack-midi support. (this means jackd should not show up with "-X__" when it has loaded, and so this can be checked with pgrep jackd)

]
Last edited by mtlwstlk on Thu Aug 22, 2019 9:33 pm, edited 1 time in total.
mtlwstlk
Established Member
Posts: 5
Joined: Tue Aug 20, 2019 8:06 pm

Re: Jackd+A2J with Systemd startup

Post by mtlwstlk »

Amended these changes for the service unit files, as well as implementing "SystemdService=" in the dbus files meant I had to remove "Exec=" from these units.

~/.config/systemd/user/dbus-org.jackaudio.service
"
[Unit]
Description=JACK 2
After=pulseaudio.service
Requires=dbus.socket
Requires=pulseaudio.service

[Service]
Type=dbus
BusName=org.jackaudio.service

ExecStartPre=-/usr/bin/killall -9 jackdbus
ExecStartPre=-/bin/sleep 2
#ExecStartPre=-/usr/bin/pacmd load-module module-null-sink
#ExecStartPre=-/bin/sleep 2
ExecStartPre=-/usr/bin/pacmd set-default-sink null

ExecStartPre=-/usr/bin/pacmd unload-module module-jackdbus-detect
ExecStartPre=-/bin/sleep 1
ExecStartPre=-/usr/bin/pacmd unload-module module-jack-sink
ExecStartPre=-/usr/bin/pacmd unload-module module-jack-source
ExecStartPre=-/bin/sleep 2

ExecStartPre=-/usr/bin/pacmd suspend 1
ExecStartPre=-/bin/sleep 1

ExecStart=/usr/bin/jackdbus auto

ExecStartPost=-/bin/sleep 6
ExecStartPost=/usr/bin/jack_control ds alsa
ExecStartPost=/usr/bin/jack_control dps device hw:NVidia,7
ExecStartPost=/usr/bin/jack_control dps period 512
ExecStartPost=/usr/bin/jack_control dps nperiods 3
ExecStartPost=/usr/bin/jack_control dps rate 48000
ExecStartPost=/usr/bin/jack_control dps input-latency 32
ExecStartPost=/usr/bin/jack_control dps output-latency 32
ExecStartPost=/usr/bin/jack_control dps midi-driver none
ExecStartPost=/usr/bin/jack_control eps driver alsa
ExecStartPost=/usr/bin/jack_control eps realtime True
ExecStartPost=/usr/bin/jack_control eps realtime-priority 95
ExecStartPost=-/bin/sleep 1

ExecStartPost=-/usr/bin/jack_control start
ExecStartPost=-/bin/sleep 3

ExecStartPost=-/usr/bin/pacmd load-module module-jackdbus-detect channels=2 connect=true
ExecStartPost=-/bin/sleep 3
ExecStartPost=-/usr/bin/pacmd set-default-sink jack_out
ExecStartPost=-/usr/bin/pacmd suspend-sink jack_out 0

ExecStop=-/usr/bin/jack_control exit
ExecStopPost=-/bin/sleep 2
ExecStopPost=-/usr/bin/killall -9 jackdbus
ExecStopPost=-/bin/sleep 1

ExecStopPost=-/usr/bin/pacmd unload-module module-jackdbus-detect
ExecStopPost=-/bin/sleep 1
ExecStopPost=-/usr/bin/pacmd unload-module module-jack-sink
ExecStopPost=-/usr/bin/pacmd unload-module module-jack-source
ExecStopPost=-/bin/sleep 1
ExecStopPost=-/usr/bin/pacmd set-default-sink alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1
ExecStopPost=-/bin/sleep 2
ExecStopPost=-/usr/bin/pacmd suspend 0

SuccessExitStatus=0
RemainAfterExit=yes


[Install]
WantedBy=default.target

"
-----------------------------
~/.local/share/dbus-1/services/org.jackaudio.service
"
[D-BUS Service]
Name=org.jackaudio.service
#Exec=/usr/bin/jackdbus auto

SystemdService=dbus-org.jackaudio.service
"
-----------------------------
~/.local/share/dbus-1/services/dbus-org.gna.home.a2jmidid.service
"
[Unit]
Description=alsa2jack dbus
Requires=dbus.socket
Requires=dbus-org.jackaudio.service
After=dbus-org.jackaudio.service

[Service]
Type=dbus
BusName=org.gna.home.a2jmidid

ExecStartPre=-/usr/bin/killall -9 a2jmidid
ExecStartPre=-/bin/sleep 2

ExecStart=/usr/bin/a2jmidid dbus
ExecStartPost=/bin/sleep 3
ExecStartPost=/usr/bin/a2j_control ehw
ExecStartPost=/bin/sleep 5
ExecStartPost=/usr/bin/a2j_control start

ExecStop=/usr/bin/a2j_control exit
ExecStopPost=-/bin/sleep 2
ExecStopPost=-/usr/bin/killall -9 a2jmidid

SuccessExitStatus=0
RemainAfterExit=true

[Install]
WantedBy=default.target
"

-----------------------------
~/.local/share/dbus-1/services/org.gna.home.a2jmidid.service
"
[D-BUS Service]
Name=org.gna.home.a2jmidid
#Exec=/usr/bin/a2jmidid dbus

SystemdService=dbus-org.gna.home.a2jmidid.service
"
-----------------------------
commands:

systemctl --user reenable dbus-org.gna.home.a2jmidid.service
systemctl --user reenable dbus-org.jackaudio.service
systemctl --user daemon-reload

These commands recreate the symlinks for the startup under ~/.config/systemd/user for these two new unit files,
On the next bootup these can be verified as working, by verifying with,

systemctl --user list-dependencies default.target

if any of the services failed, there would be a red marker showing which one.

should work better having dbus startup inside ~/.config/systemd/user
Post Reply