Midi connection manager

ok, before I go and write this … can someone tell me if the following exists :slight_smile:

what I want is for the rPI running headless to reconnect all midi devices in a provided configuration.

now the rules of the game are simple:

  • im talking ALSA
  • it has to support usb devices
  • it has to support virtual midi devices (like PD)

ok, so its the last two that cause the ‘issue’

we can obviously do:

aconnect "Virus TI:1" "Pure Data:0"
aconnect "Pure Data:1" "Virus TI:1"

but the issue is, when you run this you are assuming 2 things

  • Pure data is running (otherwise the PD ports are not there, so it will fail)
  • the USB device (virus in this case) has to be connected

if either is not the case aconnect will fail,
it will also fail if you restart PD, or restart the usb device.

yes, I could do a sytemctl script, that waits for PD, and make sure the device is already on, but thats not nice, I want it to be a bit more thorough than that…

and I also want if it fails, for it to ‘fix’ itself without the user getting involved by manually running something, hitting a button etc.

so what I want is something that takes these mappings and monitors for devices/ports to become available and then it makes them.
preferably the mapping is in a config file (rather than a script) so its easier for a user to edit.

surely this exists already?

For the upcoming App update, we had a need to have a ‘osc to (and back) MIDI bridge’. I could only find existing solutions with lots of external dependencies, so I decided to build a very lightweight daemon process with dependencies only on libasound and C / C++ standard libs, was going to publish it together with the App update release, but here it is: https://github.com/BlokasLabs/osc2midi

At the moment it’s not making any ALSA MIDI connections there, but I’m considering extending it (or building a separate dedicated daemon) to automatically make subscriptions for every port as they appear, there are events generated by the ALSA lib when new ports appear and old ones disappear.

The reason I’m showing the osc2midi now is to demonstrate that not a lot of code is needed to work with MIDI events on Linux, the ‘port appeared / disappeared’ events could be captured to implement automatic connection making, in case of osc2midi to its own virtual ports, or in case of a generic MIDI connection manager, make the connections based on provided rules.

In our experience, the rule ‘aconnect everything to PD and PD to everything’ goes a long way, so that’s what we’d start from. :slight_smile:

It is surprising why there’s no existing solution like that out there, or at very least it’s well hidden if it exists.

1 Like

thanks, I messed about with the asound lib a quite while back, to help integrate alsa into bela - so could dive into it again, was just hoping this was a ‘solved’ problem :slight_smile:

not sure about connecting to every port,
one thing I recently did on organelle was to allow you to connect different midi devices to different pd virtual devices, this is particular useful for MPE where one device uses all 16 channels :wink:

but keeping it simple, at least to start with, is a good idea.

hmm, will have to think about it… need to pick my battles at the moment.

My situation is a little different, but this might help: Live I have a big Pd patch that is both audio effects controlled by MIDI controllers, and a MIDI router between keyboard (-ish) controllers and synths. Depending on my mood and what I pack to a gig, which controllers and synths I have varies… but I want to run the Pi headless… so I needed a way to have the whole thing automatically patch as needed…

I use this script:

#!/bin/sh

aconnect -x

try_aconnect() {
	aconnect "$1" "$2" 2>/dev/null && echo connected $1 '-->' $2 || true
}

# in Pd, four midi devices appear as 0~3 in, and 4~7 out
try_aconnect 'Faderfox UC44':0 'Pure Data':0
try_aconnect 'Elektron Digitakt':0 'Pure Data':1
try_aconnect 'Circuit':0 'Pure Data':2
try_aconnect 'PreenFM mk2':0 'Pure Data':2
try_aconnect 'pisound':0 'Pure Data':2
try_aconnect 'nanoKEY2':0 'Pure Data':3
try_aconnect 'DU-TOUCH S':0 'Pure Data':3
try_aconnect 'Launchpad Pro':1 'Pure Data':3

try_aconnect 'Pure Data':4 'Faderfox UC44':0
try_aconnect 'Pure Data':5 'Elektron Digitakt':0
try_aconnect 'Pure Data':6 'Circuit':0
try_aconnect 'Pure Data':6 'PreenFM mk2':0
try_aconnect 'Pure Data':6 'pisound':0

Essentially, I define four ports, for four different functions in my Pd patch:

  • port 0: main knob/fader controller
  • port 1: drum machine
  • port 2: synth
  • port 3: note controller

Then this script just attempts to hook up everything… and is tolerant of missing devices.

I’ve arranged for this script to run after both as the CLICK_3 script, and at the end of the CLICK_1 script.
I can thus re-connect devices on the fly.

1 Like

Hey! We have built a minimal background service for making MIDI connections automatically, called amidiauto

It’s integrated by default in Patchbox OS image, but it can be installed manually by doing

sudo apt-get update && sudo apt-get install amidiauto

It categorizes all of the MIDI ports available on the system into ‘software’ (such as Pure Data, Super Collider, etc…) and ‘hardware’ ones (such as MIDI DIN5, external USB controllers, touchosc2midi, pisound-ctl, etc…), and automatically makes the connections between the hardware and software ports as soon as a new port appears. If a device or software has more than single MIDI input and output, only the first pair gets used.

I think this covers most of the user use cases, but of course some special case configuration may be necessary to suit particular setup. At the moment this facility is not implemented, but we’d be very interested in feedback or even pull requests for the tool. :slight_smile:

4 Likes

Hi,
Im using MODEP rightnow, and installed amidiauto as you stated. However, it doesnt automatically connect my devices, what am I missing? Or do I have to do it with a script?
Basically wanted to connect my OP-1 with OP-Z, and also send Midi signals to OP-1 through the normal midi channels of Pisound.
When I do it manually, it works ofcourse, but I dont want to write all the aconnect commands everytime I plug them. Thanks for helping!

modep@modep:~ $ aconnect -l

client 0: ‘System’ [type=kernel]
0 'Timer ’
1 'Announce ’
Connecting To: 128:0, 130:0
client 14: ‘Midi Through’ [type=kernel]
0 ‘Midi Through Port-0’
Connecting To: 130:0[real:0]
Connected From: 130:0
client 16: ‘OP-Z’ [type=kernel,card=0]
0 'OP-Z MIDI 1 ’
Connecting To: 130:0[real:0]
Connected From: 130:0
client 20: ‘OP-1 Midi Device’ [type=kernel,card=1]
0 ‘OP-1 Midi Device MIDI 1’
Connecting To: 129:0, 130:0[real:0]
Connected From: 129:0, 130:0
client 28: ‘pisound’ [type=kernel,card=3]
0 ‘pisound MIDI PS-0Z7FE7V’
Connecting To: 130:0[real:0]
Connected From: 130:0
client 129: ‘pisound-ctl’ [type=user,pid=671]
0 'pisound-ctl ’
Connecting To: 130:0[real:0], 20:0
Connected From: 130:0, 20:0
modep@modep:~ $

Hi, by default amidiauto makes connections only between the software and hardware ports, however, it can make the desired connections if they are explicitly defined in /etc/amidiauto.conf, see Patchbox and ORAC for some details how it works. (you probably already have 1.01 version, so you don’t have to install manually as shown in my post)

Here’s a config that should work for you, feel free to adjust :slight_smile:

[allow]
* <-> *            # Allow automatically connecting hw and sw ports
OP-1 <-> OP-Z      # Connect OP-1 and OP-Z in both directions.
                   # Use <- or -> instead to connect in only one direction
                   # a -> b would cause output from a to be connected to b input.
pisound -> OP-1

After changing the config, restart amidiauto:

sudo systemctl restart amidiauto
3 Likes

Thats sounds great, but somehow the folder “etc” is not writable, how can I create the file then?
Thanks!
edit: Im trying it with Patchbox, newest version I think

That’s normal, system config files are usually with restricted permissions for safety and inconvenience purposes :).

Do:

sudo nano /etc/amidiauto.conf

to run the editor as root, paste in the contents, hit ctrl+x, then hit y to save and exit.

2 Likes

Thanks a lot, first it didnt work, but after Updating amidiauto it works like a charm!
I just thought I have the newest amidiauto after installing Patchbox but wasnt like that.
anyway thanks a lot

1 Like

If I only want to make connections between all plugged hardwares, am I simply add the lines in amidiauto.conf as

[allow]
hw <-> hw

What I need is to use Pisound as a MIDI host, for the connection with Digitakt and several controllers.

1 Like

At the moment you have to explicitly mention the names of the virtual MIDI ports if you want connections of ports in the same hardware category.

So something like:

[allow]
pisound <-> digitakt

and more lines like above. Use aconnect -l to see the port names, also the rules are case sensitive.

1 Like

Thanks @Giedrius! It’s working!

I’m curious to know what the Midi Through MIDI device is.

Also, may I know is there a way I can run SuperCollider before amidiauto? Imagine I would like to do this:
scide MIDIClient.init MIDIIn.connectAll &

I’m not sure if I can do above on IDE, I want SC starts and initialize MIDIClient and connect all available ports, then let amidiauto recognize all the virtual ports from SC. I don’t need s.boot; as all I would like to do is use SC only as a MIDI dispatcher.

I don’t think the order of startup is important, amidiauto does its work for all the ports it found on startup, as well as any ports appearing dynamically at runtime. Other software is free to make their own connections, amidiauto won’t disconnect them.

1 Like

Thanks! It is wonderful!

Hi Giedrius,
Ive just realized when I activate the ORAC 2.0 Module, that the Amidiauto Midi configs dont work anymore, but all the devices connects to Pure Data. When I deactivate the ORAC Module, everything works again. Any idea to solve this?
Here is the aconnect -l output with Orac activated:

client 0: 'System' [type=kernel]
0 'Timer           '
1 'Announce        '
    Connecting To: 128:0, 129:0

client 14: ‘Midi Through’ [type=kernel]
0 ‘Midi Through Port-0’
Connecting To: 129:0[real:0]
Connected From: 129:0
client 20: ‘pisound’ [type=kernel,card=1]
0 ‘pisound MIDI PS-0Z7FE7V’
Connecting To: 129:0[real:0], 130:0
Connected From: 129:0, 130:1
client 24: ‘OP-Z’ [type=kernel,card=2]
0 'OP-Z MIDI 1 ’
Connecting To: 129:0[real:0], 130:0
Connected From: 129:0, 130:1
client 28: ‘OP-1 Midi Device’ [type=kernel,card=3]
0 ‘OP-1 Midi Device MIDI 1’
Connecting To: 129:0[real:0], 130:0
Connected From: 129:0, 130:1
client 130: ‘Pure Data’ [type=user,pid=594]
0 ‘Pure Data Midi-In 1’
Connected From: 20:0, 24:0, 28:0, 129:0, 131:0[real:0], 133:0, 134:0
1 ‘Pure Data Midi-Out 1’
Connecting To: 20:0, 24:0, 28:0, 129:0[real:0], 132:0, 134:0
client 131: ‘MEC MIDI OUTPUT’ [type=user,pid=653]
0 'MIDI OUT ’
Connecting To: 130:0[real:0], 129:0[real:0]
client 132: ‘RtMidiIn Client’ [type=user,pid=794]
0 'TouchOSC Bridge ’
Connected From: 130:1, 129:0
client 133: ‘RtMidiOut Client’ [type=user,pid=794]
0 'TouchOSC Bridge ’
Connecting To: 130:0, 129:0[real:0]
client 134: ‘pisound-ctl’ [type=user,pid=807]
0 'pisound-ctl ’
Connecting To: 130:0, 129:0[real:0]
Connected From: 130:1, 129:0

Yes, ORAC module has its own amidiauto.conf file, you can customize it here:

/usr/local/patchbox-modules/orac/amidiauto.conf

and re-activate ORAC.

Hi, another questions here regarding Mac to Midi over Wifi.
I have Pi and Mac in the same network, and want to send Sync data from Mac to Pisound,
I have set it up as stated here: https://help.ableton.com/hc/en-us/articles/209071169-Sending-and-receiving-MIDI-messages-using-a-virtual-MIDI-network

Thats working, and Mac seems to send data to Pisound, but the devices connected to PIsound by USB dont receive the Sync data from Mac.
When I check on aconnect RtMidi Client is connected to everything, I also tried to connect RtMidiOut to OP-1 for example with amidiconf, using it with ORAC currently.
Any idea what could be missing? Thanks!

client 0: 'System' [type=kernel]
    0 'Timer           '
    1 'Announce        '
        Connecting To: 128:0, 129:0
client 14: 'Midi Through' [type=kernel]
    0 'Midi Through Port-0'
        Connecting To: 129:0[real:0]
        Connected From: 129:0
client 20: 'pisound' [type=kernel,card=1]
    0 'pisound MIDI PS-0Z7FE7V'
        Connecting To: 24:0, 129:0[real:0], 131:0, 28:0
        Connected From: 129:0, 131:1
client 24: 'OP-Z' [type=kernel,card=2]
    0 'OP-Z MIDI 1     '
        Connecting To: 129:0[real:0], 131:0, 28:0
        Connected From: 20:0, 129:0, 130:0, 131:1
client 28: 'OP-1 Midi Device' [type=kernel,card=3]
    0 'OP-1 Midi Device MIDI 1'
        Connecting To: 131:0, 129:0[real:0]
        Connected From: 131:1, 20:0, 24:0, 130:0, 134:0, 129:0
client 130: 'pisound-ctl' [type=user,pid=674]
    0 'pisound-ctl     '
        Connecting To: 24:0, 129:0[real:0], 131:0, 28:0
        Connected From: 129:0, 131:1
client 131: 'Pure Data' [type=user,pid=593]
    0 'Pure Data Midi-In 1'
        Connected From: 20:0, 24:0, 130:0, 129:0, 132:0, 132:0[real:0], 134:0, 28:0
    1 'Pure Data Midi-Out 1'
        Connecting To: 20:0, 24:0, 130:0, 129:0[real:0], 133:0, 28:0
client 132: 'MEC MIDI OUTPUT' [type=user,pid=677]
    0 'MIDI OUT        '
        Connecting To: 131:0, 131:0[real:0], 129:0[real:0]
client 133: 'RtMidiIn Client' [type=user,pid=773]
    0 'TouchOSC Bridge '
        Connected From: 131:1, 129:0
client 134: 'RtMidiOut Client' [type=user,pid=773]
    0 'TouchOSC Bridge '
        Connecting To: 131:0, 129:0[real:0], 28:0

How did you check that the Raspberry Pi is actually receiving the messages from your Mac? You ought to have some process on RPi side able to receive the Mac MIDI messages, I don’t think I see such a process in the attached client list.

Then I probably didnt see it. I was thinking that RtMidiIn and Out are connected to 28:0, which in that time is OP-1. What kind of information do you need to verify?
I can only say that I had added sucessfully PIsound / Rapsberry to the Virtual Midi Network.
Thanks, Im sorry If my information isnt accurate, trying to do my best.