Recent

Author Topic: Interfacing to MIDI (sequencer) devices via ALSA on Linux  (Read 12516 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Interfacing to MIDI (sequencer) devices via ALSA on Linux
« on: April 13, 2023, 02:55:36 pm »
A few months ago I spent some time transcribing some of the ALSA libraries so that they could be called either statically or dynamically, my intention being to update the files at https://github.com/MarkMLl/asound to include better sequencer (i.e. MIDI) facilities.

This was a substantial amount of work but I believe it is worth doing since having a library loaded dynamically means that a program can be tolerant of missing libraries etc., but also being able to load it statically can simplify debugging.

I'm currently putting together a test program, my intention being to collect data from one or more client:port sources and send it to a preexisting destination.

I've got source and destination identification working properly. I believe I've got subscriptions from source to destination working properly, but I'm a little unclear as to what's actually /needed/. The place I'm actually having problems is with explicit data transfer for specified events, and passing those to a filter.

Does anybody have experience in this area, plus a bit of time to discuss/help?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Fred vS

  • Hero Member
  • *****
  • Posts: 3721
    • StrumPract is the musicians best friend
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #1 on: April 14, 2023, 10:19:01 pm »
Hello Mark.

I will test all your code with pleasure but there: https://github.com/MarkMLl/asound It seems that the last commit was 2 years ago (and I already try this).

Note that I have poor skill in MIDI things, at the moment no MIDI real keyboard connected, only a virtual with VMPK.

What do you want to test?

Fre;D 

 
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #2 on: April 15, 2023, 09:25:36 am »
Tentative code attached, look for examples/MidiFilter which is a GUI program but at the moment expects command lines and does its stuff before creating anything graphical.

Command line is

MidiFilter source [source] destination

where source and destination are formatted as client:port (i.e. like aconnect). There may be an additional parameter to specify a dynamically-loaded plugin for filtering but that's not implemented yet.

(Edited to add: could usefully create a temporary destination if it doesn't exist yet, to make getting the order of loading programs and connecting devices easier.)

I haven't tried dynamic linkage of the asound libraries yet.

At present it creates and then destroys a subscription, but something's wrong when it tries to free subscriptions which makes me suspicious of the transcribed declarations (originally h2pas, but with a fair amount of extra work to get comments in in a form that Lazarus likes).

Transfer between existing source(s) and destination works. But I don't know how to get selected event types directed to the filter procedure.

All help very much appreciated. If we can get this working adequately I'll treat it as a test of the program that I use to create static and dynamic libraries based on a .inc file and release it.

MarkMLl
« Last Edit: April 15, 2023, 10:35:46 am by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

bobby100

  • Sr. Member
  • ****
  • Posts: 300
    • Malzilla
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #3 on: April 15, 2023, 09:55:50 am »
I have no ALSA experience, but in WindowsMM and in portmidi, you register your callback procedures to the interfaces/ports, and there you get all your messages. You can filter what you do not need, and send the messages to the destination.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #4 on: April 15, 2023, 10:08:31 am »
I have no ALSA experience, but in WindowsMM and in portmidi, you register your callback procedures to the interfaces/ports, and there you get all your messages. You can filter what you do not need, and send the messages to the destination.

In that case *you* work through the libraries and find the function that registers a callback. 'Cause I'm blowed if I can.

This isn't WindowsMM etc., and I've done an adequate amount with these libraries in the past (as you can obviously see from my GitHub repos). But they aren't exactly simple, and the few examples I've seen are either simplistic or written by people directly involved with the ALSA internals with minimal explanation.

In the past I've written a GUI-oriented program that selected an input device (two-manual keyboard) and split/transposed etc., but I think that predated ALSA's introduction of subscriptions so I'm keeping it at arm's length.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

bobby100

  • Sr. Member
  • ****
  • Posts: 300
    • Malzilla
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #5 on: April 15, 2023, 12:02:10 pm »
Last chapter (Filter application) here: https://alsa-project.org/alsa-doc/alsa-lib/seq.html
If I understand it correct, you need to wait for events in a loop. It is a bit silly if there is no mechanism that would announce events to your app...

EDIT: also http://fundamental-code.com/midi/
Code: C  [Select][+][-]
  1. void midi_process(snd_seq_event_t *ev)
  2. {
  3.     if ((ev->type == SND_SEQ_EVENT_NOTEON)||(ev->type == SND_SEQ_EVENT_NOTEOFF)) {
  4.         const char *type = (ev->type == SND_SEQ_EVENT_NOTEON) ? "on " : "off";
  5.  
  6.         printf("[%d] Note %s: %2x vel(%2x)\n", ev->time.tick, type,
  7.                                                ev->data.note.note,
  8.                                                ev->data.note.velocity);
  9.     }
  10.     else if(ev->type == SND_SEQ_EVENT_CONTROLLER)
  11.         printf("[%d] Control:  %2x val(%2x)\n", ev->time.tick,
  12.                                                 ev->data.control.param,
  13.                                                 ev->data.control.value);
  14.     else
  15.         printf("[%d] Unknown:  Unhandled Event Received\n", ev->time.tick);
  16. }
  17.  
  18. int main()
  19. {
  20.     midi_open();
  21.     while (1)
  22.         midi_process(midi_read());
  23.     return -1;
  24. }

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #6 on: April 15, 2023, 12:19:46 pm »
Last chapter (Filter application) here: https://alsa-project.org/alsa-doc/alsa-lib/seq.html
If I understand it correct, you need to wait for events in a loop. It is a bit silly if there is no mechanism that would announce events to your app...

In that case feel free to fix my code.

There's specific provision in the API for filtering by event type: see the third para of the link you cited. That's what I'm trying to use, to keep everything simple.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Fred vS

  • Hero Member
  • *****
  • Posts: 3721
    • StrumPract is the musicians best friend
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #7 on: April 15, 2023, 02:15:34 pm »
Tentative code attached, look for examples/MidiFilter which is a GUI program but at the moment expects command lines and does its stuff before creating anything graphical.

Command line is

MidiFilter source [source] destination

...

Hello Mark.

I have compiled your demo MidiFiler on Linux Debian 12 but I do not catch how to test it.
Could you give the command line that you use on your Debian system (maybe I'll have the click) ?

Thanks.

Fre;D

« Last Edit: April 15, 2023, 03:33:40 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #8 on: April 15, 2023, 03:33:46 pm »
I have compiled your demo MidiFiler on Linux Debian 12 but I do not catch how to test it.
Could you give the command line that you use on your Debian system (maybe I'll have the click) ?

What I'm doing is:

In one shell session:

Code: Text  [Select][+][-]
  1. $ amidi -p virtual -d
  2.  

Anything that connects to that will now get dumped.

In another shell session:

Code: Text  [Select][+][-]
  1. /usr/local/src/asound/trunk/examples$ aconnect -l
  2.  
  3. client 0: 'System' [type=kernel]
  4.     0 'Timer           '
  5.     1 'Announce        '
  6. client 14: 'Midi Through' [type=kernel]
  7.     0 'Midi Through Port-0'
  8. client 16: 'Keystation Pro 88' [type=kernel,card=0]
  9.     0 'Keystation Pro 88 MIDI 1'
  10.     1 'Keystation Pro 88 MIDI 2'
  11. client 20: 'MD100' [type=kernel,card=1]
  12.     0 'MD100 MIDI 1    '
  13.         Connected From: 128:0
  14. client 128: 'WatchP0x' [type=user,pid=1885]
  15.     0 'WatchP0x        '
  16.         Connecting To: 20:0
  17. client 129: 'Client-129' [type=user,pid=84482]
  18.     0 'Virtual RawMIDI '
  19.  
  20. /usr/local/src/asound/trunk/examples$ ./MidiFilter-x86_64-linux-qt5 16:0 129:0
  21.  
  22. Subscribing 1 sources, PID 84500
  23.  

The first command there lists the current devices, note 129:0 at the end which is the copy of amidi dumping anything sent to it.

The second command sets up a subscription between 16:0 (a keyboard) and the debug output.

If instead you run the program from the Lazarus IDE with the parameters    16:0 129:0    you should see it set up a subscription. It will, in actual fact, handle multiple source devices in the same way that  cat  handles multiple source files.

On termination, subscriptions are freed (resulting in an abort, which is one of the problems).

If you look at the latter part of the program, you'll see a loop which I expected to read any events which were marked as filtered. However so far /everything/ appears to be handled inside ALSA, so I am not at all sure how one's supposed to capture the filtered stuff.

Any insights you can contribute would be much appreciated: /if/ the filtering facility does break into subscriptions (which is what I was initially expecting) it would vastly simplify this sort of code.

As you'll see from a README I've left in the examples directory, I was originally hoping that I'd be able to map controls on my M-Audio keyboard to the Bristol/Brighton softsynths. However I suspect that they've never actually gained MIDI handling other than key events and the pitch/mod wheels.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Fred vS

  • Hero Member
  • *****
  • Posts: 3721
    • StrumPract is the musicians best friend
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #9 on: April 15, 2023, 04:30:25 pm »
Hello Mark.

OK, I get this with virtual keyboard : VMPK:

Code: Bash  [Select][+][-]
  1. > ~/D/a/t/examples> aconnect -l
  2. client 0: 'System' [type=kernel]
  3.     0 'Timer           '
  4.         Connecting To: 142:0
  5.     1 'Announce        '
  6.         Connecting To: 142:0
  7. client 14: 'Midi Through' [type=kernel]
  8.     0 'Midi Through Port-0'
  9. client 128: 'Client-128' [type=user,pid=617671]
  10.     0 'Virtual RawMIDI '
  11. client 129: 'MIDI In' [type=user,pid=617757]
  12.     0 'in              '
  13. client 142: 'PipeWire-System' [type=user,pid=1101]
  14.     0 'input           '
  15.         Connected From: 0:1, 0:0
  16. client 143: 'PipeWire-RT-Event' [type=user,pid=1101]
  17.     0 'input
           '

Hum, all this is totally new for me.  :-[
I will study it and write you later.

Fre;D
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #10 on: April 15, 2023, 04:51:35 pm »
So which is your (virtual) keyboard? is that 129:0 with amidi being 128:0?

In that case I'd expect you to be able to connect from the keyboard to amidi using

$ aconnect 129:0 128:0

followed later by one of

$ aconnect -d 129:0 128:0

or

$ aconnect -x

In which case you should at present see the same behaviour from

$ MidiFilter-x86_64-linux-qt5 -d 129:0 128:0

(with minor variation depending on widget set etc.) except that it should tear the connection down on termination.

Obviously you can pass the  129:0 128:0  as the commandline parameters inside the IDE.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Fred vS

  • Hero Member
  • *****
  • Posts: 3721
    • StrumPract is the musicians best friend
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #11 on: April 15, 2023, 05:29:24 pm »
So which is your (virtual) keyboard? is that 129:0 with amidi being 128:0?

Maybe... ( I am not yet MIDI guru, only explorer  :-X).
I will learn/try your code tomorrow, I need first to jump into this MIDI-aconnect things.

Thanks for your highly appreciated jump into this, maybe old, but still highly used MIDI protocol ( still unknown for me ).
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #12 on: April 15, 2023, 05:51:12 pm »
My suspicion is that they've been adding bits to ALSA without documenting them properly... but ain't it always so?

I could probably recycle some of my old code, but particularly for a demo would rather "do it the right way" if possible.

When I last did this, my (GUI) program selected an existing (physical) device (e.g. a keyboard) and created a (virtual) device to which an app (e.g. Piano Booster or Rosegarden) could in turn connect.

The alternative it to have two (physical or virtual) devices, then to use something like aconnect to set up a subscription between them. This was how I anticipated using this program, since when I started thinking about it I anticipated having (e.g.) my M-Audio keyboard plugged in with one of the Bristol/Brighton frontends running and using it to map between the multitude of controls on the keyboard to the multitude of controls on the softsynth (e.g. the M-Audio drawbars driving Hammond drawbars).

The M-Audio keyboard is programmable and I believe it shipped with a CD containing some variant of the Evolution Librarian, but that was a long time ago and an operating system far, far away :-) And in any case, this should be a good demo.

MarkMLl
« Last Edit: April 15, 2023, 08:53:44 pm by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Fred vS

  • Hero Member
  • *****
  • Posts: 3721
    • StrumPract is the musicians best friend
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #13 on: April 16, 2023, 09:27:04 pm »
Hello Mark.

I am fighting here with amidi + aconnect but with no luck.

Here my result with aconnect -l:
Code: Bash  [Select][+][-]
  1. > ~/D/a/t/examples [SIGABRT]> aconnect -l
  2. client 0: 'System' [type=kernel]
  3.     0 'Timer           '
  4.         Connecting To: 142:0
  5.     1 'Announce        '
  6.         Connecting To: 142:0
  7. client 14: 'Midi Through' [type=kernel]
  8.     0 'Midi Through Port-0'
  9. client 128: 'FLUID Synth (1090)' [type=user,pid=1090]
  10.     0 'Synth input port (1090:0)'
  11. client 129: 'VMPK Input' [type=user,pid=20940]
  12.     0 'in              '
  13. client 130: 'Client-130' [type=user,pid=21032]
  14.     0 'Virtual RawMIDI '
  15. client 142: 'PipeWire-System' [type=user,pid=1091]
  16.     0 'input           '
  17.         Connected From: 0:1, 0:0
  18. client 143: 'PipeWire-RT-Event' [type=user,pid=1091]
  19.     0 'input  

So I suppose that the (virtual) keyboard is client 129: 'VMPK Input'
and amidi is 128.

But doing this ( even with sudo or other amidi ) I get this:
Code: Bash  [Select][+][-]
  1.  > aconnect 129:0 128:0
  2. Connection failed (Operation not permitted)

With your MidiFilter, I get nearly the same error (so your code seems to work):
Code: Bash  [Select][+][-]
  1. > ~/asound/trunk/examples/MidiFilter-x86_64-linux-gtk2 -d 129:0 128:0
  2. Subscribing 1 sources, PID 25822
  3. Invalid ALSA subscription for source 0 (129:0): Operation not permitted.
  4. free(): invalid pointer
  5. fish: Job 1, '/home/fred/Downloads/asound/tru…' terminated by signal SIGABRT (Abort)

I am not sure I could help for something about alsa midi ( apart testing and trying to understand how it works ).
« Last Edit: April 16, 2023, 09:37:09 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

MarkMLl

  • Hero Member
  • *****
  • Posts: 8515
Re: Interfacing to MIDI (sequencer) devices via ALSA on Linux
« Reply #14 on: April 16, 2023, 10:16:09 pm »
Just about to head for a post-gardening shower and a good book... let me think about it.

I wonder why VMPK is labelled "in" rather than "input"?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018