int main() { snd_seq_t *handle; int err; err = snd_seq_open(&handle, "default", SND_SEQ_OPEN_INPUT, 0); if (err < 0) { fprintf(stderr, "%s\n", snd_strerror(-err)); exit(1); } snd_seq_set_client_name(handle, "Yo!"); int port_number = snd_seq_create_simple_port(handle, "my port", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC); snd_seq_event_t *event; for (;;){ snd_seq_event_input(handle, &event); printf("Type: %d\n", event->type); if (snd_seq_ev_is_note_type(event)){ printf("Note: %d\n", event->data.note.note); printf("Velocity: %d\n", event->data.note.velocity); } printf("Source: %d:%d\n", event->source.client, event->source.port); printf("Destination: %d:%d\n", event->dest.client, event->dest.port); } return 0; }
void AlsaMidiInputThread::readEvent() { m_mutex.lock(); /* Wait for input data */ do { AlsaMidiInputDevice* device = NULL; snd_seq_event_t* ev = NULL; /* Receive an event */ snd_seq_event_input(m_alsa, &ev); // Find a device matching the event's address. If one isn't // found, skip this event, since we're not interested in it. uint uid = AlsaMidiUtil::addressToVariant(&ev->source).toUInt(); if (m_devices.contains(uid) == true) device = m_devices[uid]; else continue; Q_ASSERT(device != NULL); uchar cmd = 0; uchar data1 = 0; uchar data2 = 0; //qDebug() << "ALSA MIDI event received !" << ev->type; if (snd_seq_ev_is_control_type(ev)) { switch (ev->type) { case SND_SEQ_EVENT_PGMCHANGE: cmd = MIDI_PROGRAM_CHANGE; data1 = ev->data.control.value; data2 = 127; break; case SND_SEQ_EVENT_CONTROLLER: cmd = MIDI_CONTROL_CHANGE | ev->data.control.channel; data1 = ev->data.control.param; data2 = ev->data.control.value; break; case SND_SEQ_EVENT_PITCHBEND: cmd = MIDI_PITCH_WHEEL | ev->data.control.channel; data1 = (ev->data.control.value + 8192) & 0x7f; data2 = (ev->data.control.value + 8192) >> 7; break; case SND_SEQ_EVENT_KEYPRESS: cmd = MIDI_NOTE_AFTERTOUCH | ev->data.note.channel; data1 = ev->data.note.note; data2 = ev->data.note.velocity; break; case SND_SEQ_EVENT_CHANPRESS: cmd = MIDI_CHANNEL_AFTERTOUCH | ev->data.control.channel; data1 = ev->data.control.value; break; default: break; } } else if (snd_seq_ev_is_note_type(ev)) { if (ev->type == SND_SEQ_EVENT_NOTEOFF) cmd = MIDI_NOTE_OFF | ev->data.note.channel; else if (ev->data.note.velocity == 0 && ev->data.note.off_velocity == 0) cmd = MIDI_NOTE_OFF | ev->data.note.channel; else cmd = MIDI_NOTE_ON | ev->data.note.channel; data1 = ev->data.note.note; data2 = ev->data.note.velocity; } else if (snd_seq_ev_is_queue_type(ev)) { if (device->processMBC(ev->type) == false) continue; if (ev->type == SND_SEQ_EVENT_START) cmd = MIDI_BEAT_START; else if(ev->type == SND_SEQ_EVENT_STOP) cmd = MIDI_BEAT_STOP; else if(ev->type == SND_SEQ_EVENT_CONTINUE) cmd = MIDI_BEAT_CONTINUE; else if(ev->type == SND_SEQ_EVENT_CLOCK) cmd = MIDI_BEAT_CLOCK; qDebug() << "MIDI clock: " << cmd; } // ALSA API is a bit controversial on this. snd_seq_event_input() says // it ALLOCATES the event but snd_seq_free_event() says this is not // needed because the event IS NOT allocated. No crashes observed // either way, so I guess freeing nevertheless is a bit safer. snd_seq_free_event(ev); uint channel = 0; uchar value = 0; if (QLCMIDIProtocol::midiToInput(cmd, data1, data2, device->midiChannel(), &channel, &value) == true) { device->emitValueChanged(channel, value); // for MIDI beat clock signals, // generate a synthetic release event if (cmd >= MIDI_BEAT_CLOCK && cmd <= MIDI_BEAT_STOP) device->emitValueChanged(channel, 0); } } while (snd_seq_event_input_pending(m_alsa, 0) > 0);