monome / norns

norns is many sound instruments.
http://monome.org
GNU General Public License v3.0
633 stars 147 forks source link

unable to use all usb midi ports #536

Closed TheTechnobear closed 5 years ago

TheTechnobear commented 6 years ago

under usb a particular midi device may have a number of ports. this is used extensively for things like midi hubs (as opposed to usb hubs), but also for things like simple USB to midi din converts

however, it appears that alsa is only creating a rawmidi file for ports 0 (and norns uses rawmidi)

example: we@norns:~ $ amidi -l Dir Device Name IO hw:0,0 pisound MIDI PS-3TG77SW IO hw:2,0,0 Ableton Push 2 MIDI 1 IO hw:2,0,1 Ableton Push 2 MIDI 2 IO hw:3,0,0 Virus TI MIDI IO hw:3,0,1 Virus TI Synth IO hw:4,0,0 MIDIMATE II MIDI 1 IO hw:4,0,1 MIDIMATE II MIDI 2 IO hw:5,0,0 Pyramid MIDI USB MIDI 1

we can see here 3 devices, Push2, Virus TI and the midi mate (usb to din converter) , all have multiple midi ports.

now if we look at /dev/snd/midi*

we@norns:~ $ ls -al /dev/snd/midiC* crw-rw---- 1 root audio 116, 8 Aug 31 19:00 /dev/snd/midiC0D0 crw-rw-rw- 1 root audio 116, 72 Aug 31 19:00 /dev/snd/midiC2D0 crw-rw---- 1 root audio 116, 104 Aug 31 19:00 /dev/snd/midiC3D0 crw-rw---- 1 root audio 116, 136 Sep 1 12:51 /dev/snd/midiC4D0 crw-rw---- 1 root audio 116, 168 Sep 1 12:51 /dev/snd/midiC5D0

we can see we only end up with one rawmidi file for each device.

an in practice what I found is that this midi can only be ever sent to the first port

so in the above this means...


Im not sure if alsa can be configured to create a rawmidi file for each subdevice, this would be the no code change solution. but I couldn't figure it out from the alsa documentation, I think its configured in /usr/share/alsa/alsa.conf, but that a pretty cryptic file... anyone with more experience in alsa, no what magic runes may make this work?

on other projects Ive avoided rawmidi and instead used the alsa devices were you can specify the full device (e.g. hw:3,0,1) so never had an issue with this.

artfwo commented 6 years ago

supporting multiple alsa ports was my intention when i started implementing midi in norns (my keys also expose 2 virtual ports in alsa), but we dropped the idea for the reasons i mentioned in #527. i never had problems with the 2nd port being inaccessible though. did you manage to receive any data from the 2nd port for a given device by reading from /dev/snd/midiCxDy?

TheTechnobear commented 6 years ago

as I showed, we are only getting one rawmidi file, and neither the midimate nor virus, does data from the second port appear on the D0 device. (not surprising, as they'd have to put in separate files as otherwise you could not differentiate)

I understand why simplifying/unifying is attractive, but really the udev is just being used to monitor changes in the system, past that point, you are basically moving to different apis for grid,midi, hid anyway - so don't really see why this requires using rawmidi/files - if this brings limitations/complications

can you not just use udev monitor to monitor for changes to the "snd" subsystem, and then use that as a hint to recheck for new alsa devices? its not like users are constantly plugging/unplugging, so an extra couple of api calls is hardly an issue.

(in fact given the new 'devices' menu, its arguable at device scan is only needed at I) startup II) when the user selects this menu item)

… and then norns would have full alsa support, so not only multiple ports, but also things like virtual midi ports from applications.

you say you have managed to get a 2nd port working? have you an example? does it list an extra /dev/snd/midiCxDy device, I assume it must so that you can switch between them, otherwise if you send data, how does it know which port to send to?

I did also have a look at alsa config, and if you check that you will see the default for subdevice is -1, which the comment says use the first … so it does appear its not configured for multiple devices. unfortunately, online I cannot find a single example of additional being specified.... as most apps don't appear to use rawmidi, rather the hw:3,0,1 format

artfwo commented 6 years ago

It's not so much about simplification, but rather unification of the device detection mechanism.

alsa sequencer api has notifications for new ports in the system, which is completely not compatible with device_monitor (it deals with midi ports instead of devices) and we actually used that in the beginning.

I didn't do anything to get the 2nd port on my keys working, the keyboard (Novation Impulse 49) works 100% without doing anything special, so I'm curious how it's different for you. Say, can you do something like cat /dev/snd/midiC3D0 and see if any data comes from the virus synth when it's used as a controller?

Regading 'full alsa support' and virtual ports for applications. I seriously doubt this is necessary. We have laptops for use-cases that need that functionality. In the norns context it looks like creeping featurism.

TheTechnobear commented 6 years ago

yes, Ive already tried to cat it, and also write code to see if the port contains data - and no dice.

and as I already said, It cannot work like that... that 'file' is pure midi data, so could only contain midi channel (in status byte) , so there would be no way to attach it to a particular port/sub device....

perhaps the impulse 49 has a different setup.. as you can see, Ive actually 3 devices, and all don't have the extra files

perhaps you could post your output from amidi -l and ls -al /dev/snd/midiC*

with the impulse in... Id be interested to see how this looks.

It's not so much about simplification, but rather unification of the device detection mechanism alsa sequencer api has notifications for new ports in the system, which is completely not compatible > with device_monitor (it deals with midi ports instead of devices) and we actually used that in the beginning.

why does it matter its different? there is a load of code that is different between midi, hid and grid - why is it important that the detection mechanism in particular is unified?

virtual midi, will be very useful to you if (for example) you ever decide to use Pure Data as an engine. Im a bit confused why you would start closing off doors so early in a platforms lifecycle.

artfwo commented 6 years ago

perhaps you could post your output from amidi -l and ls -al /dev/snd/midiC*

I don't have the keys with me right now, but it was just one device in /dev and 2 ports in amidi -l.

there is a load of code that is different between midi, hid and grid - why is it important that the detection mechanism in particular is unified?

well, the i/o code is naturally different, but the detection code could be (again, naturally) unified, so why not? it saves some bits in structures and logic.

virtual midi, will be very useful to you if (for example) you ever decide to use Pure Data as an engine. Im a bit confused why you would start closing off doors so early in a platforms lifecycle.

in this case, the engine<->matron communication should still be restricted to engine commands and polls. interfacing with the hardware is a job for scripts in a typical use-case.

i'm certainly not closing any doors, norns is free software and i'm just the occasional contributor, so what i'm doing is trying to find the solution to your problem that wouldn't result in rewriting the entire midi subsystem, which doesn't seem like a necessary step. it looks like rawmidi does have a subdevice query and setting mechanism, have you looked into that?

TheTechnobear commented 6 years ago

As I said in my original post, yes I’d read the documentation, and believed it was possible , but could find no solid example involving rawmidi.
Even google did not yield anything relevant.

As an experienced Linux programmer, I’m used to looking up documentation and also trying to fine examples - but there seems to be a lack in this particular case.

Hence, I came here looking for someone with experience in alsa configuration, to determine if this was possible.

( as I said I’m familiar with doing this via the normal alsa api, just not for rawmidi)

Are you 100% sure you had the data from both ports? I cannot see why they would be combined - perhaps it’s just that the data comes in on the first port and so worked.

I guess we will see as more people use Norns with different midi devices then we will see different use cases

TheTechnobear commented 6 years ago

my use cases are not relevant to norns - I'll close this issue.

catfact commented 6 years ago

are you closing this because of my comment on the other issue? hm.

anyways, my understanding is that you can pass different subdevice strings to snd_rawmidi_open(), which include the port number.

have you tried this with the virus/midimate? https://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2rawmidi_8c-example.html

[ed] nevermind, i read that wrong. still, what happens if you pass all three indices to snd_rawmidi_open() ?

i think the use case of using a MIDImate or Virus is certainly relevant.

responding to some other points:

why is it important that the detection mechanism in particular is unified?

dunno if i'd call it "important" but it's certainly cleaner, more lightweight, and less code. if anyone wants to fully incorporate an ALSA detection module into the lua glue layer, we can merge that. as mentioned, we did this once but concluded it was unnecessary - my understanding was that opening a given device gave you all ports. (but this could be wrong, or could be an effect of alsa.conf - again i haven't witnessed anything first hand.)

but, like everyone else, i suspect all can actually be done with rawmidi.

/usr/share/alsa/alsa.conf, but that a pretty cryptic file...

i agree, but that is where you must look. i'm not going to look there because i don't own a single midi device (and probably haven't seriously used one for at least 15 years.)

catfact commented 6 years ago

bumping this, it really is an issue with plenty of devices. (apparently ableton push 1 uses the second port for "user" data and the first port for live-specific data... or something.)

junklight commented 5 years ago

Just to add to this. iConnectMidi exposes 4 ports on a computer DIN1,DIN2,USB,None - on the Norns it only uses the first for output which means you have to edit the default config of the iConnect on a separate computer to make it output to the USB so you can use it with USB in devices. This is not really ideal - it would be great if you could just select the USB port. Will look in more detail at some point

"my understanding was that opening a given device gave you all ports. " - very much not the case for output on the iConnect - it outputs only to the first available port

okyeron commented 5 years ago

digging around on this...

I think the norns midi code needs to look for rawmidi "subdevices" and assign them as needed

Check out Alsa rawmidi reference - snd_rawmidi_info_get_subdevices_avail and also snd_rawmidi_info_set_subdevice

catfact commented 5 years ago

alas, i don't think so - we will have some weird situation where the device list is just one layer in a tree...?

unless - has anyone with a test device followed up on my suggestion to "pass all three indices to snd_rawmidi_open()?" is that totally stupid? if it's not, then i agree, the subdevice listing could happen in device_monitor.

i think the answer if we want to continue with minimal changes to the existing structure is to figure out appropriate changes to alsa.conf - as suggested, but i guess we are having a hard time with that.

so i'd guess we should go back to alsaseq somehow - i'm not an expert on this (again, not really a MIDI user) and apologize if my early input was responsible for the current problems.

finally, i'm up for considering a complete rewrite for this system as a 2.x milestone - maybe using JACK midi.

okyeron commented 5 years ago

SC has a robust midi implementation - and it's been pitched as as a possible engine, but it seems like this would need to be a separate layer?

catfact commented 5 years ago

yeah that's not the direction we wanna go in... i appreciate that people want to use SC midi event composition but we are trying to move away from dependence on SC and make norns more directly support multiple sound engine platforms (PD is high on the list.)

in any case, a good amount of work has been put into device management on the norns / in lua, with MIDI learn for script-defined parameters, &c &c.

really, bringing back alsaseq should be a pretty minor task to address this one piece of glue - from real device ports to "virtual devices."

ericmoderbacher commented 5 years ago

It would be really nice to use my Push 1 with my Norns. So i thought maybe i would try to take a look into whats going on here, after a couple hours looking through Alsas documentation I feel out of my depths. I do not have much experience with Linux. I'm starting to doubt that I can be helpful, but I would like to keep trying.

I see that there are two discussed solutions, adjusting alsa.conf. Or using alsaseq instead of raw midi. I'm guessing i should try the config file first. I'm focusing on the config file now, if anyone has resources they can share on alsa that might be more helpful than the documentation i would appreciate it.

okyeron commented 5 years ago

Wanted to check in on this again...

What needs to happen to "bring back alsaseq"? (and should this be alsa-seq instead?)

Did some digging tonight again on playing a midi file - and having the midi play a norns synth engine. This does not currently seem possible with norns in 2.1.0. Without any midi devices attached there is no midi port to play a file to. Maybe norns could create a local virtual midi port on startup?

NoraCodes commented 3 years ago

Hi! Found this while trying to get MIDI passthrough to work (see this Lines thread). Either ALSA Seq MIDI or JACK MIDI (via a2jmidid or even just by exposing native JACK MIDI ports from Matron) would enable this, at least for advanced users. I would be absolutely happy to help implement that, with a little guidance, if there is interest.

artfwo commented 3 years ago

we used to have an ALSA seq implementation in the past, but dropped that in favor of unified monitoring logic, see the discussion above.

it's technically possible to dig that code out, but the i/o part is the simplest here - the change would also require rewriting the monitoring part for midi ports, midi out methods, etc. to use ALSA seq too.

i think the problem you're trying to solve could still be solved on the script level, unless there is something wrong with midi vports, but then that would be a completely different issue.

catfact commented 3 years ago

@NoraCodes, this request (to use a non-exclusive API) seems like it has drifted from the original issue here (which is still solved AFAIK,) so maybe better as a new issue... well, whatever, we're already here.

i don't think any of us have a specific problem with going back to alsa-seq, but it does represent substantially more complexity in device monitoring and representation. i'm not sure we will have time to assist with the design.

but beyond that, there are two points i'd like to make:

NoraCodes commented 3 years ago

this request (to use a non-exclusive API) seems like it has drifted from the original issue here

Fair enough, and I'm sorry for causing that. I came into this issue because I'd exhausted my ability to configure Norns to do what I wanted according to my Linux knowledge, and this was the most related discussion I could find.

the linked forum topic looks to me like a simple misuse of the virtual ports systm

I guess. I think the ultimate solution would be along the lines of the "module" system that's been discussed a few times on Lines, which I would hope would include the ability to register multiple handlers for various events, including MIDI. That's an avenue I'd also love to help with, if that would be useful, but of course that's a larger design effort.

you just have to compose the callbacks

True, but I am deeply averse to modifying every single script I run on Norns to enable this (honestly not that wacky, I don't think) use case. That's not to say I expect anyone else to do the work to enable it, but it would be nice if we could arrive at a scalable solution to the specific problem of "I want incoming MIDI to go to Norns and other things at the same time", or even the general problem of "I want to do more than one thing at once when a MIDI message comes in" that doesn't require modifying every script.

(I'll note that I could just call the script's MIDI handler for a given device in my own MIDI handler if I could get access to the user's MIDI handler consistently but that would mean I would have to have access to it when Passthrough was set up, which I don't always, since the MIDI handler can be and often is registered dynamically later in the script.)

the only purpose of the feature would be allowing non-norns processes to use the device.

This is correct. I recognize that this isn't a supported use case, but it would be really nice to be able to use Norns as a MIDI host converter while also using the same MIDI stream within Norns. As is, I am working around this using an extra MIDI interface.

catfact commented 3 years ago

the general problem of "I want to do more than one thing at once when a MIDI message comes in" that doesn't require modifying every script.

i would add something (up to you) to the low-level MIDI handler that is called before dispatching to vports. (or alternatively, extend the vport handler to be either a function or a table of fnuctions.) in other words, that is a problem with the scripting layer, which can be solved in the scripting layer.

https://github.com/monome/norns/blob/main/lua/core/midi.lua#L410

https://github.com/monome/norns/blob/main/lua/core/vport.lua#L3

[ed] in other words: yes, as you say, something like "modules." but this seems like relatively low effort to me. (chaining a few lua functions, vs making all our C stuff work with alsa-seq.)

clearly the other ideas/issues need other solutions. (e.g. i'm not sure offhand why virtual can't be used in multiple vports, but that seems like a simple feature add/fix.)

NoraCodes commented 3 years ago

Yeah, I think that's a sensible approach. Maybe a table of functions which are called before the foreground script's callback, so you can de-register your handler when unloading a "module"? But it might be more appropriate to wait until further work on modules happens to do this.

i'm not sure offhand why virtual can't be used in multiple vports, but that seems like a simple feature add/fix.

I'm going to look into that as a more immediate fix to this specific problem and think about module stuff in a more general sense, if that seems good to you.