+ } else if (flags & (PORT_EVENT|PORT_SEQUENCE)) {
+ /* FIXME: The checks here for bufs.count().n_midi() > index shouldn't
+ be necessary, but the mapping is illegal in some cases. Ideally
+ that should be fixed, but this is easier...
+ */
+ if (flags & PORT_MIDI) {
+ if (flags & PORT_INPUT) {
+ index = in_map.get(DataType::MIDI, midi_in_index++, &valid);
+ } else {
+ index = out_map.get(DataType::MIDI, midi_out_index++, &valid);
+ }
+ if (valid && bufs.count().n_midi() > index) {
+ /* Note, ensure_lv2_bufsize() is not RT safe!
+ * However free()/alloc() is only called if a
+ * plugin requires a rsz:minimumSize buffersize
+ * and the existing buffer if smaller.
+ */
+ bufs.ensure_lv2_bufsize((flags & PORT_INPUT), index, _port_minimumSize[port_index]);
+ _ev_buffers[port_index] = bufs.get_lv2_midi(
+ (flags & PORT_INPUT), index, (flags & PORT_EVENT));
+ }
+ } else if ((flags & PORT_POSITION) && (flags & PORT_INPUT)) {
+ lv2_evbuf_reset(_atom_ev_buffers[atom_port_index], true);
+ _ev_buffers[port_index] = _atom_ev_buffers[atom_port_index++];
+ valid = true;
+ }
+
+ if (valid && (flags & PORT_INPUT)) {
+ Timecode::BBT_Time bbt;
+ if ((flags & PORT_POSITION)) {
+ if (_session.transport_frame() != _next_cycle_start ||
+ _session.transport_speed() != _next_cycle_speed) {
+ // Transport has changed, write position at cycle start
+ tmap.bbt_time(_session.transport_frame(), bbt);
+ write_position(&_impl->forge, _ev_buffers[port_index],
+ tmetric, bbt, _session.transport_speed(),
+ _session.transport_frame(), 0);
+ }
+ }
+
+ // Get MIDI iterator range (empty range if no MIDI)
+ MidiBuffer::iterator m = (index != nil_index)
+ ? bufs.get_midi(index).begin()
+ : silent_bufs.get_midi(0).end();
+ MidiBuffer::iterator m_end = (index != nil_index)
+ ? bufs.get_midi(index).end()
+ : m;
+
+ // Now merge MIDI and any transport events into the buffer
+ const uint32_t type = LV2Plugin::urids.midi_MidiEvent;
+ const framepos_t tend = _session.transport_frame() + nframes;
+ ++metric_i;
+ while (m != m_end || (metric_i != tmap.metrics_end() &&
+ (*metric_i)->frame() < tend)) {
+ MetricSection* metric = (metric_i != tmap.metrics_end())
+ ? *metric_i : NULL;
+ if (m != m_end && (!metric || metric->frame() > (*m).time())) {
+ const Evoral::MIDIEvent<framepos_t> ev(*m, false);
+ LV2_Evbuf_Iterator eend = lv2_evbuf_end(_ev_buffers[port_index]);
+ lv2_evbuf_write(&eend, ev.time(), 0, type, ev.size(), ev.buffer());
+ ++m;
+ } else {
+ tmetric.set_metric(metric);
+ bbt = metric->start();
+ write_position(&_impl->forge, _ev_buffers[port_index],
+ tmetric, bbt, _session.transport_speed(),
+ metric->frame(),
+ metric->frame() - _session.transport_frame());
+ ++metric_i;
+ }
+ }
+ } else if (!valid) {
+ // Nothing we understand or care about, connect to scratch
+ _ev_buffers[port_index] = silent_bufs.get_lv2_midi(
+ (flags & PORT_INPUT), 0, (flags & PORT_EVENT));
+ }
+ buf = lv2_evbuf_get_buffer(_ev_buffers[port_index]);
+ } else {
+ continue; // Control port, leave buffer alone
+ }
+ lilv_instance_connect_port(_impl->instance, port_index, buf);
+ }
+
+ // Read messages from UI and push into appropriate buffers
+ if (_from_ui) {
+ uint32_t read_space = _from_ui->read_space();
+ while (read_space > sizeof(UIMessage)) {
+ UIMessage msg;
+ if (_from_ui->read((uint8_t*)&msg, sizeof(msg)) != sizeof(msg)) {
+ error << "Error reading from UI=>Plugin RingBuffer" << endmsg;
+ break;
+ }
+ uint8_t body[msg.size];
+ if (_from_ui->read(body, msg.size) != msg.size) {
+ error << "Error reading from UI=>Plugin RingBuffer" << endmsg;
+ break;
+ }
+ if (msg.protocol == urids.atom_eventTransfer) {
+ LV2_Evbuf* buf = _ev_buffers[msg.index];
+ LV2_Evbuf_Iterator i = lv2_evbuf_end(buf);
+ const LV2_Atom* const atom = (const LV2_Atom*)body;
+ if (!lv2_evbuf_write(&i, nframes, 0, atom->type, atom->size,
+ (const uint8_t*)(atom + 1))) {
+ error << "Failed to write data to LV2 event buffer\n";
+ }
+ } else {
+ error << "Received unknown message type from UI" << endmsg;