{
assert(count().get(DataType::MIDI) > i);
- MidiBuffer& mbuf = get_midi(i);
LV2Buffers::value_type b = _lv2_buffers.at(i * 2 + (input ? 0 : 1));
LV2_Evbuf* evbuf = b.second;
- lv2_evbuf_set_type(evbuf, old_api ? LV2_EVBUF_EVENT : LV2_EVBUF_ATOM);
+ lv2_evbuf_set_type(evbuf, old_api ? LV2_EVBUF_EVENT : LV2_EVBUF_ATOM);
lv2_evbuf_reset(evbuf, input);
- if (input) {
- DEBUG_TRACE(PBD::DEBUG::LV2,
- string_compose("%1 bytes of MIDI waiting @ %2\n",
- mbuf.size(), (void*) mbuf.data()));
-
- LV2_Evbuf_Iterator i = lv2_evbuf_begin(evbuf);
- const uint32_t type = LV2Plugin::urids.midi_MidiEvent;
- for (MidiBuffer::iterator e = mbuf.begin(); e != mbuf.end(); ++e) {
- const Evoral::MIDIEvent<framepos_t> ev(*e, false);
-#ifndef NDEBUG
- DEBUG_TRACE(PBD::DEBUG::LV2,
- string_compose("\tMIDI event of size %1 @ %2\n",
- ev.size(), ev.time()));
- for (uint16_t x = 0; x < ev.size(); ++x) {
- std::stringstream ss;
- ss << "\t\tev[" << x << "] = " << std::hex << (int) ev.buffer()[x] << std::dec << std::endl;
- DEBUG_TRACE (PBD::DEBUG::LV2, ss.str());
- }
-#endif
- lv2_evbuf_write(&i, ev.time(), 0, type, ev.size(), ev.buffer());
- }
- }
return evbuf;
}
DEBUG_TRACE (PBD::DEBUG::LV2, string_compose ("\tByte[%1] = %2\n", x, (int) data[x]));
}
#endif
- mbuf.push_back(frames, size, data);
+ if (type == LV2Plugin::urids.midi_MidiEvent) {
+ // TODO: Make Ardour event buffers generic so plugins can communicate
+ mbuf.push_back(frames, size, data);
+ }
}
}
_bpm_control_port = 0;
_freewheel_control_port = 0;
_latency_control_port = 0;
- _position_seq_port_idx = std::numeric_limits<uint32_t>::max();
_next_cycle_start = std::numeric_limits<framepos_t>::max();
_next_cycle_speed = 1.0;
_block_length = _engine.frames_per_cycle();
flags |= PORT_AUDIO;
} else if (lilv_port_is_a(_impl->plugin, port, _world.ev_EventPort)) {
flags |= PORT_EVENT;
+ flags |= PORT_MIDI; // We assume old event API ports are for MIDI
} else if (lilv_port_is_a(_impl->plugin, port, _world.atom_AtomPort)) {
LilvNodes* buffer_types = lilv_port_get_value(
_impl->plugin, port, _world.atom_bufferType);
_impl->plugin, port, _world.atom_supports);
if (lilv_nodes_contains(buffer_types, _world.atom_Sequence)) {
+ flags |= PORT_SEQUENCE;
if (lilv_nodes_contains(atom_supports, _world.midi_MidiEvent)) {
- flags |= PORT_MESSAGE;
- } else {
- flags |= PORT_ATOM;
+ flags |= PORT_MIDI;
}
if (lilv_nodes_contains(atom_supports, _world.time_Position)) {
- _position_seq_port_idx = i;
+ flags |= PORT_POSITION;
}
}
lilv_nodes_free(buffer_types);
LV2Plugin::has_message_output() const
{
for (uint32_t i = 0; i < num_ports(); ++i) {
- if ((_port_flags[i] & (PORT_MESSAGE|PORT_ATOM)) && _port_flags[i] & PORT_OUTPUT) {
+ if ((_port_flags[i] & PORT_SEQUENCE) &&
+ (_port_flags[i] & PORT_OUTPUT)) {
return true;
}
}
BufferSet& silent_bufs = _session.get_silent_buffers(bufs_count);
BufferSet& scratch_bufs = _session.get_scratch_buffers(bufs_count);
uint32_t const num_ports = parameter_count();
+ uint32_t const nil_index = std::numeric_limits<uint32_t>::max();
uint32_t audio_in_index = 0;
uint32_t audio_out_index = 0;
uint32_t midi_in_index = 0;
uint32_t midi_out_index = 0;
uint32_t atom_port_index = 0;
- bool valid;
for (uint32_t port_index = 0; port_index < num_ports; ++port_index) {
void* buf = NULL;
- uint32_t index = 0;
+ uint32_t index = nil_index;
PortFlags flags = _port_flags[port_index];
+ bool valid = false;
if (flags & PORT_AUDIO) {
if (flags & PORT_INPUT) {
index = in_map.get(DataType::AUDIO, audio_in_index++, &valid);
? bufs.get_audio(index).data(offset)
: scratch_bufs.get_audio(0).data(offset);
}
- } else if (flags & (PORT_EVENT|PORT_MESSAGE)) {
+ } 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_INPUT) {
- index = in_map.get(DataType::MIDI, midi_in_index++, &valid);
- _ev_buffers[port_index] = (valid && bufs.count().n_midi() > index)
- ? bufs.get_lv2_midi(true, index, flags & PORT_EVENT)
- : silent_bufs.get_lv2_midi(true, 0, flags & PORT_EVENT);
- buf = lv2_evbuf_get_buffer(_ev_buffers[port_index]);
- } else {
- index = out_map.get(DataType::MIDI, midi_out_index++, &valid);
- _ev_buffers[port_index] = (valid && bufs.count().n_midi() > index)
- ? bufs.get_lv2_midi(false, index, flags & PORT_EVENT)
- : scratch_bufs.get_lv2_midi(false, 0, flags & PORT_EVENT);
- buf = lv2_evbuf_get_buffer(_ev_buffers[port_index]);
- }
- } else if (flags & (PORT_ATOM)) {
- assert(_atom_ev_buffers && _atom_ev_buffers[atom_port_index]);
- if (flags & PORT_INPUT) {
+ 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) {
+ _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 (port_index == _position_seq_port_idx) {
- Timecode::BBT_Time bbt;
+ 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) {
- // Something has changed, write the position at cycle start
+ // 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);
}
+ }
- // Write a position event for every metric change within this cycle
- while (++metric_i != tmap.metrics_end() &&
- (*metric_i)->frame() < _session.transport_frame() + nframes) {
- MetricSection* section = *metric_i;
- tmetric.set_metric(section);
- bbt = section->start();
+ // 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
+ LV2_Evbuf_Iterator i = lv2_evbuf_end(_ev_buffers[port_index]);
+ 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(),
- section->frame(),
- section->frame() - _session.transport_frame());
+ metric->frame(),
+ metric->frame() - _session.transport_frame());
+ ++metric_i;
}
}
- } else {
- lv2_evbuf_reset(_atom_ev_buffers[atom_port_index], false);
- _ev_buffers[port_index] = _atom_ev_buffers[atom_port_index++];
+ } 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]);
- assert(buf);
} else {
continue; // Control port, leave buffer alone
}
midi_out_index = 0;
for (uint32_t port_index = 0; port_index < num_ports; ++port_index) {
PortFlags flags = _port_flags[port_index];
+ bool valid = false;
// Flush MIDI (write back to Ardour MIDI buffers)
- if ((flags & PORT_OUTPUT) && (flags & (PORT_EVENT|PORT_MESSAGE))) {
+ if ((flags & PORT_OUTPUT) && (flags & (PORT_EVENT|PORT_SEQUENCE))) {
const uint32_t buf_index = out_map.get(
DataType::MIDI, midi_out_index++, &valid);
if (valid) {
}
// Write messages to UI
- if (_to_ui && (flags & PORT_OUTPUT) && (flags & (PORT_MESSAGE|PORT_ATOM))) {
+ if (_to_ui && (flags & PORT_OUTPUT) && (flags & (PORT_EVENT|PORT_SEQUENCE))) {
LV2_Evbuf* buf = _ev_buffers[port_index];
for (LV2_Evbuf_Iterator i = lv2_evbuf_begin(buf);
lv2_evbuf_is_valid(i);