diff options
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/lv2_plugin.h | 16 | ||||
-rw-r--r-- | libs/ardour/buffer_set.cc | 30 | ||||
-rw-r--r-- | libs/ardour/lv2_plugin.cc | 105 |
3 files changed, 76 insertions, 75 deletions
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h index 51fa5a2987..66c44884ea 100644 --- a/libs/ardour/ardour/lv2_plugin.h +++ b/libs/ardour/ardour/lv2_plugin.h @@ -179,7 +179,6 @@ class LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee float* _bpm_control_port; ///< Special input set by ardour float* _freewheel_control_port; ///< Special input set by ardour float* _latency_control_port; ///< Special output set by ardour - uint32_t _position_seq_port_idx; ///< Index of Sequence port for position framepos_t _next_cycle_start; ///< Expected start frame of next run cycle double _next_cycle_speed; ///< Expected start frame of next run cycle PBD::ID _insert_id; @@ -190,13 +189,14 @@ class LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee uint32_t* type); typedef enum { - PORT_INPUT = 1, - PORT_OUTPUT = 1 << 1, - PORT_AUDIO = 1 << 2, - PORT_CONTROL = 1 << 3, - PORT_EVENT = 1 << 4, - PORT_MESSAGE = 1 << 5, - PORT_ATOM = 1 << 6 + PORT_INPUT = 1, ///< Input port + PORT_OUTPUT = 1 << 1, ///< Output port + PORT_AUDIO = 1 << 2, ///< Audio (buffer of float) + PORT_CONTROL = 1 << 3, ///< Control (single float) + PORT_EVENT = 1 << 4, ///< Old event API event port + PORT_SEQUENCE = 1 << 5, ///< New atom API event port + PORT_MIDI = 1 << 6, ///< Event port understands MIDI + PORT_POSITION = 1 << 7 ///< Event port understands position } PortFlag; typedef unsigned PortFlags; diff --git a/libs/ardour/buffer_set.cc b/libs/ardour/buffer_set.cc index c2be5ca007..1f8317ffe2 100644 --- a/libs/ardour/buffer_set.cc +++ b/libs/ardour/buffer_set.cc @@ -257,34 +257,11 @@ BufferSet::get_lv2_midi(bool input, size_t i, bool old_api) { 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; } @@ -311,7 +288,10 @@ BufferSet::flush_lv2_midi(bool input, size_t i) 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); + } } } diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 928c97a32e..b48c962d0c 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -274,7 +274,6 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) _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(); @@ -405,6 +404,7 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) 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); @@ -412,13 +412,12 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) _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); @@ -1066,7 +1065,8 @@ bool 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; } } @@ -1485,17 +1485,18 @@ LV2Plugin::connect_and_run(BufferSet& bufs, 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); @@ -1508,59 +1509,78 @@ LV2Plugin::connect_and_run(BufferSet& bufs, ? 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 } @@ -1601,9 +1621,10 @@ LV2Plugin::connect_and_run(BufferSet& bufs, 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) { @@ -1612,7 +1633,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs, } // 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); |