Support for non-USB MIDI ports (Ex: virtual, network, etc )

You were right! If I stop matron it works!

Unfortunately then I can’t load matron back again. So I would probably have to modify it and recompile it.

why not?

matron is controlled by a systemd service. the service confiuration is specified here:

and it is installed to /etc/systemd/system/norns-matron.service. as you can see, all this does is wrap the matron process in our websocket stdio wrapper tool so that it can be controlled remotely by the web IDE.

you could edit the systemd scripts to start up your tool before starting matron. (there is also norns.target for example, that could be the best place.) then matron will probably throw the same ALSA error when it tries to grab the device, but it might not be a real problem. to avoid that error, yes you would have to edit matron source to ignore the device.

for development purposes, it can sometimes be more convenient to use the scripts ~/norns/start.sh and ~/norns/stop.sh, which do the same tasks as the systemd services.

Hi! Thanks so much for your patience. In a very hacky way I’m ignoring my midi device…

void handle_device(struct udev_device *dev) {
    const char *action = udev_device_get_action(dev);
    const char *node = udev_device_get_devnode(dev);
    const char *subsys = udev_device_get_subsystem(dev);

    const char *name = get_device_name(dev);
    printf(" --> handle_device( %s )\n", name);
    if (strcmp(name,"nanoKONTROL2") == 0)
        return;

    if (action == NULL) {
        // scan
        if (node != NULL) {
            device_t t = check_dev_type(dev);

            if (t >= 0 && t < DEV_TYPE_COUNT) {
                dev_list_add(t, node, get_device_name(dev));
            }
        }
    } else {
...

Then loading my program. It creates a virtual midi port ,(midigyver / sequencer ) which I can’t see on the norns.
I tried restarting norns using:

sudo systemctl stop norns-matron 
sudo systemctl start norns-matron 

but I get the same result. The virtual device is not visible for norns but still visible by ALSA

$ aconnect -i -o -l 
    client 0: 'System' [type=kernel]
        0 'Timer           '
        1 'Announce        '
    client 14: 'Midi Through' [type=kernel]
        0 'Midi Through Port-0'
    client 20: 'nanoKONTROL2' [type=kernel,card=1]
        0 'nanoKONTROL2 MIDI 1'
            Connecting To: 129:0
            Connected From: 130:0[real:0]
    client 128: 'midigyver' [type=user,pid=17264]
        0 'sequencer       '
    client 129: 'midigyver' [type=user,pid=17264]
        0 'nanoKONTROL2*   '
            Connected From: 20:0
    client 130: 'midigyver' [type=user,pid=17264]
        0 'nanoKONTROL2*   '
            Connecting To: 20:0[real:0]

Any suggestion or hint why norns is not aware of it?

Thanks!

Oh I see there is a longer conversation regarding non-usb midi devices here maybe I could re use @TheTechnobear diff https://github.com/monome/norns/pull/532

oh, i see. so this is really a separate issue: you want norns to see the virtual midi device you created, but ignore the physical port

yes, the norns device detection system is just designed to watch the USB device tree and assign appropriate handlers.

my point in the linked issue was that one probably would not want to support non-USB devices by hacking the device discovery mechanisms. technobear’s example was GPIO midi, and yours is virtual midi. in both cases, you don’t need discovery because the first case is hardwired and the second is a kown path to a device that you just created.

but whatever

if you do want to use that diff, you would want to look carefully at what happens downstream from handle_device and probably make some changes so that it is correctly ignoring non-midi, non-hid, non-serial hardware and TTY devices. i think once you do that, better solutions will occur to you anyway.

Yeah… you are right that diff is not really good for me because my port is virtual. Any plan to add ALSA midi devices? or MIDI over BlueTooth?

it’s sort of an edge case but if you are willing to help implement it, it should not be too hard.

here are two use cases not currently addressed:

  • running norns stack on non-norns hardware where midi devices can be GPIO and not just USB. (technobear’s case)
  • running non-norns software alongside norns software with virtual midi ports (your case)

both could probably be handled by same solution: more flexible device scanning logic, and the ability to explicitly open a device connection by path without waiting for it to be detected and auto-populated.

MIDI over bluetooth: no. norns hardware doesn’t have bluetooth, and supporting it requires complex weird stuff on embedded linux, which we are not gonna get into for an nonstandard use case.

Interesting! Researching how it would look like for my case (because seams RtMidi or a similar library is not an option for matron) I step upon this implementation of aconnect here

But later I saw this,


do you think it would work to use this kernel modules to trick matron that the virtual devices are “real” once ??

I guess I’m going to give it a change…

i’m sorry if i was unclear.

i believe that the problem is not that matron “can’t see” virtual devices from ALSA, but that it is not looking for them because it is explicitly first looking for USB devices, then getting ALSA device handles from them. you could indeed try technobear’s diff to see whether this affects your situation. you may get some garbage downstream after that, and you will additionally have to tell matron device discovery to ignore the physical port.

as a test, i’d try just inverting the logic so that matron device disccovery scans everything that isn’t a USB device.

we could of course use something like RtMidi library, but it would not really solve your use case - you would then be left with the problem of two ALSA clients (via rtmidi) fighting for the same device.

so either way, we need more flexible and configurable logic around device discovery for various “nonstandard” use cases. this actually extends beyond MIDI, there are also issues like distinguishing between ACM devices that expect different protocols (e.g. crow and trellis-based DIY grid controllers) -

so the solution currently in the pipeline is to add a layer of scripting and rich configuration to the device acquisition. this is planned for norns 3.0 (or maybe 3.x) which has been in development for a while now and does not have a planned release date (situation of the world has not made it easy.)

if you can hack a behavior that works for you, it would be great to see it so that we can support that in the next version of the system.

1 Like

Oh… I see… I have done that before, seams to try to open every single file in the /dev folder but never steps into something I can recognize like the virtual port. That’s where I got the assumption that by using this way matron can’t see the virtual device and maybe by loading that kernel module it will. As a context the virtual device appears on aconnect -o but not on amidi -l.

Do you know if virtual devices have a specific “subsystem” like usb in this line

...
if (udev_device_get_parent_with_subsystem_devtype(dev, "usb", NULL)) {  
...

Sorry for all this questions and thanks again for your patience. I really would love to contribute, I’m really new to such a low level of linux audio APIs

ok, gotcha, thanks… so yeah, 'm sorry, i just don’t know the answer, not having spent a lot of time with MIDI on linux myself. (IOW i cant say off hand whether/where virtual devices appear in /dev… i just assumed that they did, somehow.)

(to make the context clear, i did write the initial implementation of device management - quick and stupid, only for monome grids and HID - but others have had their hand in since then to add the basic USB-MIDI support that we have, and to incrementally address some widening use cases. since releasing the shield, use cases have widened further and thats why we are wanting to re-architect the whole thing.)

no time like the present to get your hands dirty with the APIs! no-one is born an expert

I’d argue that it’s a worthwhile add for norns shield users - so not entirely non-standard. Also Bluetooth can be easily added to stock norns with a USB dongle.

FWIW - BTMidi is not that hard to get working (generally) and just requires a recompile of the Bluez sources - which could get wrapped into a kernel update for shield.

Now - once the connection is there, we run into the same issues being discussed in this thread. In this case - getting the device code to look at the bluetooth subsystem.

I’ve tried this but crashed and I don’t know enough to debug further in that situation.

@patriciogv I’ve done some hacking on the device_monitor code (mostly check_dev_type to get clone devices recognized) and played a bit with BT Midi, so I might be useful as a tester

( I would need to dig back in on the BT midi stuff to get a testing situation working again - it’s been many months since I looked at that)

2 Likes

i’ve used bluez on raspbi quite a bit incuding for pisound (with their rolled in support.) ive done lighting control and beacon-based systems on pi, some simple and some pushing the envelope; in every case it made the project a lot harder to maintain and a lot harder to support for end users. (because there are many things that an go wrong.) i want to spent all my limited norns time making the core features more robust, improving documentation, all of that - not adding new features that implicitly reqiure lots of work from other people to maintain.

i’m saying it’s a considerable add to the system complexity. differnet dongles are differently reliable, in fact reliability is all over the place even if it’s working perfectly and supported as a primary use case. (bluez is full of bugs (?) and kernel compatibility issues.) realistically, i’m not gonna maintain this and neither will brian and it would seem irresponsible for me to pretend otherwise.

I wasn’t aware that there are reliability issues.

I’ve only tinkered with it and it seemed fine to me, but totally understand if it’s not something you want to touch.

yeah - sorry not meaning to be defensive. just - it’s not that we haven’t considered it. i’m sure we could make someting that works great 90% of the time. but we already have to handle support cases for things in norns that work great 99% of the time, and these are things that the core devs actually use every day.

in s nutshell, bluetooth is just complicated and will always have a packet-loss / bandwidth tradeoff (physics) and its really freaking hard to guarantee any kind of latency target or a smooth experience with pairing (unless you are Apple and can QA everything in sight… and even then.)

and finallly, bluetooth just needs other system services to be running all the time and blasting RF into a system thats already susceptible to noise and pushing the envelope of compute resources. in my “turnkey” audio Pi projects i have tried to use e.g. pisounds out-of-box bluetooth support and ended up having to disable all that stuff (eg., the bluez services in patchbox OS) to make other aspects of the system reliable (e.g., buffer underruns in audio), falling back on wifi hotspots with TCP sockets.

if i’m gonna put the time into some kind of wireless midi protocol, it would be over TCP and aimed at integrating with hosts like ableton without requiring dongles. because we are already running network services all the time.

5 Likes

finally (sorry) i will say that handling other device subsystems is on the radar and will be supported eventually in a way that i think wil make everyone very happy. this will include bluetooth devices if someone is willing to take on the support and maintenance burden of bluez and kernel changes across all devices. but TLDR is yea, i don’t really want to touch that it feels like a “life is too short” thing.

2 Likes

I can’t seem to find very many details on this, but this reference says the following:

In Debian those devices are available in /dev/snd/ as well, and they also are internally linked with the old OSS device locations: /dev/midiXX.

So…assuming the virtual device shows up in /dev/snd/, then you should be able to output udev_device_get_subsystem(dev) for your virtual device to see what subsystem it’s on?

Hi! Spend the day researching and so far this is what I understood (please @zebra @okyeron feel free to deny/expand/correct/edit/confirm) :

  • Matron listen only to udev devices/events and from them they derive RAW MIDI ports
  • This represent the lower level of the ALSA stack and consist on hardware only ports it’s eventually what amidi -l list as input.
  • It’s possible to open virtual raw MIDI ports by using a kernel module and then connect any other port (virtual / real or even from Bluetooth - I think - to them) by doing:
    sudo modprobe snd_virmidi
    aconnect -lio
    aconnect [your desired midi source port] [virtual port]
    aconnect [virtual port] [your desired midi destination port]
  • BUT this still will not be recognize by matron because only listen to udev events.

Seams like a path forward to give matron more MIDI flexibility is to drop detection through udev and use ALSA MIDI Seq (sequencer) layer. This is build on top of the RAW and is designed to incorporate “real” and also virtual ports. This will allow both use virtual ports that applications open and/or bluetooth support (for those that are willing to recompile bluez in the RPi).

@zebra here you can find the code for aconnect.c and notice that it doesn’t use udev and snd_rawmidi_ api but snd_seq_ api. We could reuse part of this code to detect MIDI devices this way.

Dropping the udev/rawmidi in favor of snd_seq_ is not a minor change, and make me question.

  1. Why udev/rawmidi was use in the first place?
  2. What are the cascade of issues you for see this will bring?
  3. @zebra How do you feel about this? How much support you are willing to give to this transition?

In a personal note, I probably will keep hitting on it for a while and try to hack my way through it. My position is very comfortable because I don’t have to maintain and support a product tide to different hardware on an ever changing sea of drivers upgrades etc. So I’m not expecting much. BUT if this route is something you and the project seams interesting, I’m excited to team up and tackle it.

All the best,

Patricio

2 Likes

probably no good reason beyond expedience. the device monitoring stuff used udev because initially we just wanted to talk to usb-serial devices and HID. rawmidi required the least deviation from that pattern. (if i recall correctly)

using seq has been explored, mostly not by me but by @artfwo

i honestly don’t have a strong opinion. anyone is welcome to put the work in to make a robust solution that plays well with the existing ecosystem. if you want to do that i would be delighted. (but i will probably not be in a position to test MIDI stuff)

i don’t see a cascade of issues from setting up a clean and separate system for MIDI outside of monitoring USB device tree. but like you said, it’s not a quick hack to do that.

Thanks @zebra for the reference to those threads. Seams this have been a hot topic for a while.
I think I found a possible solution that doesn’t involve minimal full change. The plan involve loading the raw virtual Midi devices at the begining on main.c before dev_monitor_int() get excecute, this will not produce collisions with it because device_monitor.c only look for virtual devices (only ‘usb’). Once the virtual midi device is up we can use aconnect to redirect other ports to it. So far what I have done is:

  1. I took some code from amidi.c and put it on device_list.c to look up for ALSA raw virtual MIDI devices here is a commit

  2. in the raspberry pi I add the VirMidi module file so it get’s load on the kernel at boot time:

echo snd_virmidi >> /etc/modules
  1. recompile matron with my chances and reboot
  2. Sucess! Virtual Raw Midi divices are recognice

Now I’m trying to see how aconnecting things to it goes. I will report back.

@zebra is this PR material?

2 Likes