I wrote: > This is off the top of my head, so I'll have to check if this works > myself ... ;-)
Well, _of course_ I made errors. > snd_seq_queue_tempo_set_tempo(tempo, 92); The tempo value isn't bpm but the MIDI tempo value, i.e., the number of microseconds per quarter note. The correct value would be 652174 (60000000 / 92). > To send an event ... There is a problem with ALSA's rawmidi ports: ALSA doesn't know if an event to be sent is the last one, so it opens and closes the MIDI port for every event sent to it. This isn't good because it resets the port when closing. The solution is to make a connection (subscription) to the port, so that it's opened during the entire execution time of the program: snd_seq_connect_to(seq, port, 96, 0); This will cause all events sent "to the subscribers of our port" to be routed to port 96:0. > snd_seq_ev_set_dest(&ev, 64, 0); /* 64:0 */ I forgot to set the source port (but our port has number 0 anyway, so it didn't matter this time). And now we sent "to all subscribers" instead of "directly to port 96:0": snd_seq_ev_set_subs(&ev); snd_seq_ev_set_source(&ev, port); > snd_seq_ev_schedule_tick(&ev, queue, 0, 12); > snd_seq_ev_set_note(&ev, 0, 67, 127, 8); Instead of using the snd_seq_ev_xxx macros, one can use the fields of the event structure directly: ev.time.tick = 12; ev.data.note.note = 67; I have attached a little program which actually works (on my computer, your destination port probably isn't 96:0). HTH Clemens
#include <alsa/asoundlib.h> #include <unistd.h> int main() { snd_seq_t* seq; int port, queue; snd_seq_queue_tempo_t* tempo; snd_seq_event_t ev; snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); port = snd_seq_create_simple_port(seq, "my port", SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_WRITE, SND_SEQ_PORT_TYPE_APPLICATION); queue = snd_seq_alloc_queue(seq); snd_seq_queue_tempo_alloca(&tempo); snd_seq_queue_tempo_set_tempo(tempo, 60000000 / 96); snd_seq_queue_tempo_set_ppq(tempo, 4); snd_seq_set_queue_tempo(seq, queue, tempo); snd_seq_connect_to(seq, port, 96, 0); snd_seq_start_queue(seq, queue, NULL); /*snd_seq_drain_output(seq);*/ snd_seq_ev_clear(&ev); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_source(&ev, port); snd_seq_ev_schedule_tick(&ev, queue, 0, 4); snd_seq_ev_set_note(&ev, 0, 60, 127, 8); snd_seq_event_output(seq, &ev); ev.time.tick = 12; ev.data.note.note = 67; snd_seq_event_output(seq, &ev); snd_seq_drain_output(seq); sleep(4); return 0; }