Skip to main content

MIDI Forum

[Alsa Sequencer] Wh...
 
Notifications
Clear all

[Solved] [Alsa Sequencer] What is the common practice of handling a virtual UMP device when a legacy Midi host connected into it?

5 Posts
2 Users
1 Reactions
226 Views
Posts: 3
Active Member
Topic starter
 
[#5125]

Hi mate!

First time commenter here since I have a hard time on searching relevant info regardless to the ALSA sequencer where I find no info related to this problem in the ALSA documentation, nor I could find anyone handing this problem in the existing midi libraries, while the github and sourceforge discussions are a bit inactive where many of the questions remain unanswered. Seems like here is the closest place where can give me some directions to solve the problems since my problem might also involves in some basic midi 2.0 knowledge.

I am currently studying the ALSA sequencer and I have some success on building a basic midi 1.0 input and output, so I decided to build a virtual input with supporting ump; basically, I have created a port with an enum of SND_SEQ_PORT_TYPE_MIDI_UMP:

// Create an input port, but ump
const port_id = asound.snd_seq_create_simple_port(
    seq.?,
    "Zig Midi In Ump",
    asound.SND_SEQ_PORT_CAP_WRITE | asound.SND_SEQ_PORT_CAP_SUBS_WRITE,
    asound.SND_SEQ_PORT_TYPE_MIDI_GENERIC | asound.SND_SEQ_PORT_TYPE_APPLICATION | asound.SND_SEQ_PORT_TYPE_MIDI_UMP,
);

After that, I have created an async callback to receive the ump packet. is_active is a global variable so that the loop can be stopped outside the async function, while the type UmpEvent is snd_seq_ump_event_t: 

fn processUmpEvent(seq: ?*Seq) void {
    var ev: ?*UmpEvent = null;
    while (is_active) {
        if (asound.snd_seq_ump_event_input(seq.?, &ev) >= 0) {
            std.debug.print("Event type: {d}\n", .{ev.?.type});
        }
    }
}

While the program is run, since I also want to see how midi host that can't support ump behaves to my virtual input device, I decided to open a daw and trying to send something with it; unsurprisingly, although my daw recognized my virtual port, the port don't response to the event since my host didn't send ump event, but this creates some questions since I am not sure how should I handle this situation if I want to build a midi library or a midi host for example, so here are the questions:

- Is the behavior of legacy midi host recognized my virtual input device intended?
- When I build a virtual input device, do I need to check if the new incoming or target device support ump? Or my virtual device should always handle both ump and legacy format? Or I should prevent the legacy device to connect to the ump endpoint?

Please let me know if anyone needs more info for the questions, or if the question is duplicated so that I could referred to the existing discussion.


 
Posted : 16/08/2026 7:02 pm
Posts: 74
Admin
 

> While the program is run, since I also want to see how midi host that can't support ump behaves to my virtual input device, I decided to open a daw and trying to send something with it; unsurprisingly, although my daw recognized my virtual port, the port don't response to the event since my host didn't send ump event,

IIRC when you create a UMP based ALSA port it creates port 0 (The raw UMP port) - but if you give it Function Blocks it will create legacy MIDI 1.0 port on ports 1-16 (depending on setup). You can send MIDI 1.0 event to these ports and they are translated to UMP. 

Maybe https://github.com/tiwai/amidi2net might help in terms of example code.


 
Posted : 16/08/2026 7:30 pm
Posts: 3
Active Member
Topic starter
 

Thanks for your info! I think your mention of Function Block gives me a good direction in the documentation, finding something possibly I needed, and based on your finding and example, let me try to create the port as you have described.


 
Posted : 16/08/2026 7:47 pm
Posts: 3
Active Member
Topic starter
 

Good news! I manage to get my code work based on your "io-seq-common.c" example, by creating the "snd_ump_endpoint_info_t" and "snd_ump_block_info_t" with the functions "snd_seq_create_ump_endpoint()" and "snd_seq_create_ump_block()" respectively, with following the settings of your example with a hardcoded block name (My own UMP block). The callback function remains the same as the one in the question, using "snd_seq_ump_event_input" to receive the packets.

With the modified program run, I could confirm my endpoint is created properly:

 Port    Client name                      Port name
 14:0    Midi Through                     Midi Through Port-0
128:0    Zig UMP Endpoint                 MIDI 2.0
128:1    Zig UMP Endpoint                 Group 1 (My own UMP block)

With my daw pointing to the endpoint, I have sent the legacy midi event into my endpoint and I can confirmed that the old midi event are being converted to ump, and I could also recognize the note on and off packet. It even have translated into midi 2.0. I suspect the use of SND_UMP_EP_INFO_PROTO_MIDI2 does it, but I am not sure yet:

Packet:
01000000100100000011000000000000
11111111111111110000000000000000

Packet:
01000000100000000011000000000000
11111111111111110000000000000000

Packet:
01000000100100000011011100000000
11111111111111110000000000000000

Packet:
01000000100000000011011100000000
11111111111111110000000000000000

Besides, the ubuntu version also matter. Because I was using Ubuntu 24, the alsa and asoundlib was a few versions older which it didn't include the function for creating the ump endpoint and function blocks, ending with my header being outdated to the official documentation. Upgraded to Ubuntu 26 could access these missing functions.

Once again, thanks for your coding example! Otherwise, I might need much longer time to figure out how to receive my first umps.


 
Posted : 17/08/2026 1:56 am
Posts: 74
Admin
 

Excellent glad it all came together 🙂


 
Posted : 17/08/2026 10:23 pm
Share: