Amidiminder utility

Looks good :slight_smile: It’d be great to have a single utility that’d do everything.

It looks like it’s not far off - essentially it’d just need to support the automatic connection between hardware and software ports, if there’s a rule asking for it in the rules file.

What do you have in mind for the disallow rules? I think they’re mostly useful in case of having the wildcard rules which connect hw and sw together, to block certain unwanted connections.

With those 2 things sorted out, I think this could be merged into a single utility package.

1 Like

For hardware/software, I’m thinking of using something like:

[hw] <-> [sw]

The brackets would indicate a “property” of the client or port. ALSA offers a number of these:

  • Client: user | kernel
  • Port:
    • applicaiton, hardware, software
    • midi generic, midi gm, midi gm2, midi gs, midi mt32, midi xg
    • direct sample, port, sample, specific, synth, synthesizer

I’m not sure if those type flags are really used all that much, other than the client and first port set. I’m planning on seeing what all my gear and software does to see what might be useful.

For disallow, I’m thinking of explicit negative rules:

TouchOSC Bridge  <->  [sw]
TouchOSC Bridge <-x-> [hw]
# other negative rule operators:  -x-> <-x-

The question is should the rules be evaluated in the order in the file (so you could have exceptions to negative rules with positive ones that follow) - or is it easier to just sort all the negative rules to the end. I’m leaning “file order”…

One last thing, I don’t yet implement the logic that wild cards connect the first port with the appropriate direction capability. I need to check if that is important for SuperCollider or Pd… but Imagine all HW ports are already bidirectional.

Ok, sounds good. I also don’t think the Port Type gets much use out there. It seems the only useful distinction are the hw and sw port types.

As for the rule order, it might make sense to do file order, but it might also lead to user mistakes where you could place a specific disallow rule somewhere, and then further down, add a rule that allows connection to any hardware port.

The approach in amidiauto was to evaluate the strength of rules that apply to whether the connection between 2 particular ports should be made. The strength depends on how explicit the rule is, so [hw] ↔ [sw] rule would be considered a weak one, while OP-1 ↔ [sw] would be stronger and OP-1 ↔ Pisound would be the strongest one.

In addition to amidiauto rules logic, file order could be used so that the last rule would override the rule, in case a conflicting one is specified. Example:

OP-1 <-> [hw]
...
OP-1 <-x-> [hw] # This rule would override the one above

Using <-x-> (and related) and <-> (and related) would allow to get rid of [allow] and [disallow] sections altogether in the rules file.

There can definitely be one directional hardware ports.

My survey of everything I could get my hands on turned up this:

  • The only port properties that are set with any consistency are application and hardware.
  • The property software is only set by the kernel on the through port.

My inclination would be to say a port is [hw] if has the port type hardware, and [sw] if it has application. This would nicely exclude the system ports, and the kernel through port from a generic [hw] <-> [sw] rule.

There are some ports I’m just not clear about:

Touchosc seems to have different clients? There is a client touchosc that declares its port as hardware, so that one would do the right thing. There is another set of clients RtMidiIn and RtMidiOut - not sure what these are. Also, the second client has one bizarre port name!

I don’t understand what the client and port pisound-ctl is for.

Painoteq doesn’t make its ports subscribable… so it can’t be “helped” by either amidiminder or amidiauto. Sigh.

There seems to be several conflicting approaches to MIDI port handling by applications:

  • Some create ports and let the user connect externally to the application. Like Pd

  • Some let the user pick a MIDI port from within the application only. Ex.: Pianoteq. Then the app’s decision of what is an acceptable port limits you: I can’t pick the output of my looper application to go into Pianoteq! Moddep does something similar… but via the indirection of Jack’s re-exported ALSA Seq ports… it is even harder to get some software port into it!

  • Some create matching, separate in & out ports for each other port in the system - like SuperCollider.

I’m going to have to add the logic of defaulting to the first port of the appropriate direction when the port isn’t specified… Need to brood a bit on this one…

The RtMidiIn and RtMidiOut ports get created by rtmidi library that touchosc2midi uses. The touchosc ports are actually created using amidithru program to solve the port naming and port type for touchosc and possibly other ports which should fall in the ‘hardware’ group. I’ve looked into modifying touchosc2midi to avoid that, but the MIDI library it uses does not give enough control over the name or port type.

pisound-ctl is for the Pisound App, it should also be considered a hardware port. It’s hosted by osc2midi

The PDs use of MIDI ports seem to be the right way for software on Linux to do it.

The Pianoteq actually mimics how the ports work on other major platforms, but as far as I can remember, it has a setting which makes it act like PD does, where you can hook up the connections yourself.

Does SuperCollider really make a new port for each other port? Sounds very inefficient :smiley: Does it make the connections automatically too? I was looking into its MIDI use, I noticed it had many ports, but I didn’t think it depended on the count of other ports in the system.

amidiminder is finally ready for early adopter testing:

This release supports:

  • simple rules: nanoKEY2 ---> Circuit
  • complex rules: Launchpad Pro:3 <-- bicycle:synths
  • port type rules: .hw <-- nanoKey2
  • blocking rules: PreenFM <-x- nanoKey2
  • see the file amidiminder.rules file for full details

The release page has a built debian package for Raspberry Pi, built on and for Patchbox OS. You can install it with:

sudo systemctl stop amidiauto
sudo systemctl disable amidiauto
sudo dpkg -i amidiminder_0.70_armhf.deb

Installing the debian package file will set up a service to run by default, and start it immediately. The service will read a rules file placed in /etc/amidiminder.rules. If you edit that file, restart the service:

sudo systemctl restart amidiminder

It is recommended that you disable the amidiauto service if you have it, as this package contains all of that functionality, and more… and they’ll probably fight if both running.

The system is pretty verbose at the moment, see the logs with

journalctl -f amidiminder

The default rules file has these rules:

.hw <---> .app
  # Interconnect all hardware and application ports.
  # For simple set ups, this is often all you need.
  # Comment this out if you need to be more explicit about what is connected
  # to what.

RtMidiIn Client <-x- *
RtMidiOut Client -x-> *
  # Don't auto connect anything to these ports. They are generic client
  # names used by various applications, and could mean anything.

That should be equivalent to the logic that amidiauto was using.

5 Likes

That’s great! :slight_smile: We’ll look into moving to amidiminder.

I assume it still supports specifying the port number, in case a device has multiple available? It’s not mentioned in the latest information and it’d be great to explicitly mention it and the syntax in the readme/help for the program, currently it’s only visible in an example. :slight_smile:

Btw, does it update the rules file as you make connections manually using aconnect, or does it store that state somewhere else?

It does support both port numbers and port names. But yes, I need to work on the README / help / man page.

Currently it only stores observed rules in memory, not on disk. If you restart it, however, it’ll “reobserve” them, since it does a scan at start up. Nonetheless, perhaps it should store them so that such things survive restart.

Things I think it needs before a 1.0 release:

  • reload signal (SIGHUP) support (& service file support)
  • watching the rules file and auto-reloading when written
  • writing out observed rules, and possibly reloading at start (somewhere in /var/run)
  • man page / readme / help – or all three…

Anything else?

I’m very curious to see how well this works for other people in practice. I look forward to feedback.

1 Like

That’d be great - then you rarely would even have to manually edit the rules file, as you could rely on tools like aconnectgui to specify direct connections yourself, and rely on them. I guess you’d have to be careful to let the user override connections that are not initially allowed by the rules file.

What m I doing wrong? aconnectgui does not give me any connections…

patch@patchbox:~/amidiminder $ sudo amidiminder -C
reading rules from /etc/amidiminder.rules
adding rule Deluge MIDI 1:* --> Midihub MH-2KMG9CN MIDI 1:*
adding rule Deluge MIDI 1:* --> NDLR MIDI 1:*
adding rule NDLR MIDI 2:* --> Midihub MH-2KMG9CN MIDI 2:*
patch@patchbox:~/amidiminder $ sudo amidiminder -f amidiminder.rules
reading rules from amidiminder.rules
adding rule 24:0 --> 32:0
adding rule 24:0 --> 28:0
adding rule 28:1 --> 32:1
^C
patch@patchbox:~/amidiminder $ sudo systemctl restart amidiminder
patch@patchbox:~/amidiminder $ aconnectgui

Which rules file is the correct one?

When you do sudo systemctl restart amidiminder, it restarts amidiminder, and it most likely reverts to reading from /etc/amidiminder.rules.

You may double check what it’s doing by running:

sudo systemctl status amidiminder
sudo journalctl -u amidiminder

Thx for your help, I ve got to learn a lot about directories and rights as I am a linux noob

patch@patchbox:~ $ sudo sytemctl status amidiminder
sudo: sytemctl: command not found
patch@patchbox:~ $ sudo journalctl -u amidiminder
– Logs begin at Mon 2021-01-04 10:48:27 GMT, end at Mon 2021-01-04 13:35:43 GMT. –
Jan 04 12:23:43 patchbox systemd[1]: Stopping ALSA MIDI minder daemon…
Jan 04 12:23:43 patchbox systemd[1]: amidiminder.service: Main process exited, code=killed, status=1
Jan 04 12:23:43 patchbox systemd[1]: amidiminder.service: Succeeded.
Jan 04 12:23:43 patchbox systemd[1]: Stopped ALSA MIDI minder daemon.
Jan 04 12:23:44 patchbox systemd[1]: Started ALSA MIDI minder daemon.
Jan 04 12:23:44 patchbox amidiminder[2276]: reading rules from /etc/amidiminder.rules
Jan 04 12:23:44 patchbox amidiminder[2276]: adding rule Deluge MIDI 1:* --> Midihub MH-2KMG9CN MIDI
Jan 04 12:23:44 patchbox amidiminder[2276]: adding rule Deluge MIDI 1:* --> NDLR MIDI 1:*
Jan 04 12:23:44 patchbox amidiminder[2276]: adding rule NDLR MIDI 2:* --> Midihub MH-2KMG9CN MIDI 2:
Jan 04 12:27:50 patchbox systemd[1]: Stopping ALSA MIDI minder daemon…
Jan 04 12:27:50 patchbox systemd[1]: amidiminder.service: Main process exited, code=killed, status=1
Jan 04 12:27:50 patchbox systemd[1]: amidiminder.service: Succeeded.
Jan 04 12:27:50 patchbox systemd[1]: Stopped ALSA MIDI minder daemon.
Jan 04 12:27:51 patchbox systemd[1]: Started ALSA MIDI minder daemon.
Jan 04 12:27:51 patchbox amidiminder[2335]: reading rules from /etc/amidiminder.rules
Jan 04 12:27:51 patchbox amidiminder[2335]: adding rule Deluge MIDI 1:* --> Midihub MH-2KMG9CN MIDI
Jan 04 12:27:51 patchbox amidiminder[2335]: adding rule Deluge MIDI 1:* --> NDLR MIDI 1:*
Jan 04 12:27:51 patchbox amidiminder[2335]: adding rule NDLR MIDI 2:* --> Midihub MH-2KMG9CN MIDI 2:
Jan 04 12:29:51 patchbox systemd[1]: Stopping ALSA MIDI minder daemon…
Jan 04 12:29:51 patchbox systemd[1]: amidiminder.service: Main process exited, code=killed, status=1
Jan 04 12:29:51 patchbox systemd[1]: amidiminder.service: Succeeded.
Jan 04 12:29:51 patchbox systemd[1]: Stopped ALSA MIDI minder daemon.
lines 1-23…skipping…

There was a typo in sudo systemctl status command.

Btw, hit ‘end’ key to go to the very latest lines in journalctl.

1 Like

Reinstalled everything (one should mention that ‘make’ can take minutes to finish :slight_smile:
Summary: Restarted amidiminder and checked status: All ports are added but not connected by the rules.

(The journalctl is to long for a post and besides I find it kind of embarrassing to paste it here)

Just to be clear: If you are going to have the system service run amidiminder (rather than start it by hand all the time), then the rules you want to edit are in /etc/amidiminder.rules.

Looking at the output:

These rules look wrong. The format for a connection end point is device:port, so I think the rules you want are:

Deluge:MIDI 1 --> Midihub:MIDI 1
Deluge:MIDI 1 --> NDLR:MIDI 1
NDLR:MIDI 2 --> Midihub:MIDI 2

Notice that you can abbreviate the device names. Also, USB MIDI devices under linux don’t get useful names¹. So you can just use port numbers (which start at 0):

Deluge:0 --> Midihub:0
Deluge:0 --> NDLR:0
NDLR:1 --> Midihub:1

1: Why, ALSA, why??? The port names are in the USB descriptors the devices provide!!

2 Likes

Yes…yes…after days…Devices are connected and survived disconnect and restart!!

Big Thx for your help!!

Many things to do on my Zero/W: Speeding up the patching (why can´t it start that quick like the MIDIHUB does?), setting a temporary hot spot connection, and of course supporting the amidiminder project!

But first: Return to makin music…so happy!

2 Likes

right now it does only three simple virtual cables
I really want to know an answer to that naive noob question…

Midihub runs a dedicated OS for this, while Raspberry Pi Zero runs a full generic OS which takes some time to boot before it’s ready to route USB MIDI.

While what @Giedrius said is true - a Pi can still boot relatively quickly.

I measured how fast my system starts passing MIDI:

  1. connect a controller sending 16th notes over USB MIDI to the Pi
  2. connect a synth via USB MIDI to the Pi
  3. add a rule to /etc/amidiminder.rules to connect them
  4. shut down the Pi, unplug it
  5. plug in the Pi & start stopwatch
  6. wait for first note on the synth, and stop the stopwatch

My system does this in just 10 seconds. Probably not as fast as MIDIHUB starts - but fast enough for using in live performance situations.

If yours takes appreciably longer, perhaps start a different thread and we’ll help debug what it taking your system so long to boot.

Finally I had some time to test amidiminder. It works great with MidiHub and my multi-device setup.
Thank you for all the time and effort you put into it.

I struggled a little with two topics:

  1. The inital standard rule (.hw <—> .app) was much too ‘aggressive’ for my setup. Suddenly everthing was connected to everything. A hint/warning in the ‘Install’ chapter of the very good readme would be nice.

  2. A ‘rules generator’ would be nice for larger setups.

amidiminder -p | grep ‘connection’

does half of the trick and lists all active connections in almost the right syntax. However (being a linux noob) I was not able to pipe it into a file. So some cut, paste&edit was left to do. Maybe a modified -p routine can generate a .rules file out of the currently active connections.

Thanks again for the great tool.

Regards,
RoDi

1 Like