/** * process this MIDI input: pack LV2 input buffer from EventBuffer + EventConnection */ void Lv2MidiInput::process(bool rolling, jack_position_t &pos, jack_nframes_t nframes, jack_nframes_t time) { // clear atom sequence lv2_atom_sequence_clear(atomSequence); // send all notes off messages if newly stopped if(localRolling && !rolling) { Lv2MidiEvent lv2Event; lv2Event.event.time.frames = 0; lv2Event.buffer[1] = 0x7b; // CC 123 = all notes off lv2Event.buffer[2] = 0; for(uint8_t channel = 0; channel < 16; channel++) { lv2Event.buffer[0] = MidiEvent::TYPE_CONTROL + channel; lv2_atom_sequence_append_event(atomSequence, CAPACITY, &lv2Event.event); } } localRolling = rolling; // get connection and event count MidiConnection *connection = eventConnector.getConnection(); uint32_t eventCount = 0; if(connection) { connection->getSource()->process(rolling, pos, nframes, time); eventCount = connection->getEventCount(); } // get top events from buffer + connection MidiEvent* bufferEvent = eventBuffer.getNextEvent(rolling, pos, nframes); MidiEvent *connectionEvent = eventCount ? connection->getEvent(0) : 0; uint32_t eventIndex = 1; // loop while events on either buffer or connection while(bufferEvent || connectionEvent) { bool bufferNext = bufferEvent && (!connectionEvent || bufferEvent->getFrameOffset() < connectionEvent->getFrameOffset()); MidiEvent *event = bufferNext ? bufferEvent : connectionEvent; // lv2 event Lv2MidiEvent lv2Event; long frame = event->getFrameOffset(); lv2Event.event.time.frames = frame >= 0 ? frame : 0; // copy event data event->pack(&lv2Event.buffer); // append this event to sequence lv2_atom_sequence_append_event(atomSequence, CAPACITY, &lv2Event.event); // get next event if(bufferNext) { // recycle and get next buffer event ObjectCollector::scriptCollector().recycle(bufferEvent); bufferEvent = eventBuffer.getNextEvent(rolling, pos, nframes); } else { connectionEvent = eventIndex < eventCount ? connection->getEvent(eventIndex++) : 0; } } }