13
0

honor LV2 rsz:minimumSize for Atom Event buffers

This commit is contained in:
Robin Gareus 2013-06-03 00:48:17 +02:00
parent 7ab25697d2
commit a1d0093bfa
6 changed files with 58 additions and 1 deletions

View File

@ -120,6 +120,9 @@ public:
*/ */
LV2_Evbuf* get_lv2_midi(bool input, size_t i, bool old_api); LV2_Evbuf* get_lv2_midi(bool input, size_t i, bool old_api);
/** ensure minimum size of LV2 Atom port buffer */
void ensure_lv2_bufsize(bool input, size_t i, size_t buffer_capacity);
/** Flush modified LV2 event output buffers back to Ardour buffers */ /** Flush modified LV2 event output buffers back to Ardour buffers */
void flush_lv2_midi(bool input, size_t i); void flush_lv2_midi(bool input, size_t i);

View File

@ -202,6 +202,7 @@ class LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
typedef unsigned PortFlags; typedef unsigned PortFlags;
std::vector<PortFlags> _port_flags; std::vector<PortFlags> _port_flags;
std::vector<size_t> _port_minimumSize;
std::map<std::string,uint32_t> _port_indices; std::map<std::string,uint32_t> _port_indices;
/// Message send to/from UI via ports /// Message send to/from UI via ports

View File

@ -252,6 +252,25 @@ BufferSet::get(DataType type, size_t i) const
#ifdef LV2_SUPPORT #ifdef LV2_SUPPORT
void
BufferSet::ensure_lv2_bufsize(bool input, size_t i, size_t buffer_capacity)
{
assert(count().get(DataType::MIDI) > i);
LV2Buffers::value_type b = _lv2_buffers.at(i * 2 + (input ? 0 : 1));
LV2_Evbuf* evbuf = b.second;
if (lv2_evbuf_get_capacity(evbuf) >= buffer_capacity) return;
lv2_evbuf_free(b.second);
_lv2_buffers.at(i * 2 + (input ? 0 : 1)) =
std::make_pair(false, lv2_evbuf_new(
buffer_capacity,
LV2_EVBUF_EVENT,
LV2Plugin::urids.atom_Chunk,
LV2Plugin::urids.atom_Sequence));
}
LV2_Evbuf* LV2_Evbuf*
BufferSet::get_lv2_midi(bool input, size_t i, bool old_api) BufferSet::get_lv2_midi(bool input, size_t i, bool old_api)
{ {

View File

@ -115,6 +115,12 @@ lv2_evbuf_get_size(LV2_Evbuf* evbuf)
return 0; return 0;
} }
uint32_t
lv2_evbuf_get_capacity(LV2_Evbuf* evbuf)
{
return evbuf->capacity;
}
void* void*
lv2_evbuf_get_buffer(LV2_Evbuf* evbuf) lv2_evbuf_get_buffer(LV2_Evbuf* evbuf)
{ {

View File

@ -92,6 +92,12 @@ lv2_evbuf_reset(LV2_Evbuf* evbuf, bool input);
uint32_t uint32_t
lv2_evbuf_get_size(LV2_Evbuf* evbuf); lv2_evbuf_get_size(LV2_Evbuf* evbuf);
/**
Return the available capacity of the buffer
*/
uint32_t
lv2_evbuf_get_capacity(LV2_Evbuf* evbuf);
/** /**
Return the actual buffer implementation. Return the actual buffer implementation.
The format of the buffer returned depends on the buffer type. The format of the buffer returned depends on the buffer type.

View File

@ -61,6 +61,7 @@
#include "lv2/lv2plug.in/ns/ext/state/state.h" #include "lv2/lv2plug.in/ns/ext/state/state.h"
#include "lv2/lv2plug.in/ns/ext/time/time.h" #include "lv2/lv2plug.in/ns/ext/time/time.h"
#include "lv2/lv2plug.in/ns/ext/worker/worker.h" #include "lv2/lv2plug.in/ns/ext/worker/worker.h"
#include "lv2/lv2plug.in/ns/ext/resize-port/resize-port.h"
#include "lv2/lv2plug.in/ns/extensions/ui/ui.h" #include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
#ifdef HAVE_NEW_LV2 #ifdef HAVE_NEW_LV2
#include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h" #include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h"
@ -132,6 +133,7 @@ public:
LilvNode* lv2_toggled; LilvNode* lv2_toggled;
LilvNode* midi_MidiEvent; LilvNode* midi_MidiEvent;
LilvNode* rdfs_comment; LilvNode* rdfs_comment;
LilvNode* rsz_minimumSize;
LilvNode* time_Position; LilvNode* time_Position;
LilvNode* ui_GtkUI; LilvNode* ui_GtkUI;
LilvNode* ui_external; LilvNode* ui_external;
@ -408,6 +410,7 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
for (uint32_t i = 0; i < num_ports; ++i) { for (uint32_t i = 0; i < num_ports; ++i) {
const LilvPort* port = lilv_plugin_get_port_by_index(_impl->plugin, i); const LilvPort* port = lilv_plugin_get_port_by_index(_impl->plugin, i);
PortFlags flags = 0; PortFlags flags = 0;
size_t minimumSize = 0;
if (lilv_port_is_a(_impl->plugin, port, _world.lv2_OutputPort)) { if (lilv_port_is_a(_impl->plugin, port, _world.lv2_OutputPort)) {
flags |= PORT_OUTPUT; flags |= PORT_OUTPUT;
@ -442,6 +445,11 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
flags |= PORT_POSITION; flags |= PORT_POSITION;
} }
} }
LilvNode* min_size = lilv_port_get(_impl->plugin, port, _world.rsz_minimumSize);
if (min_size && lilv_node_is_int(min_size)) {
minimumSize = lilv_node_as_int(min_size);
}
lilv_node_free(min_size);
lilv_nodes_free(buffer_types); lilv_nodes_free(buffer_types);
lilv_nodes_free(atom_supports); lilv_nodes_free(atom_supports);
} else { } else {
@ -452,6 +460,7 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate)
} }
_port_flags.push_back(flags); _port_flags.push_back(flags);
_port_minimumSize.push_back(minimumSize);
} }
_control_data = new float[num_ports]; _control_data = new float[num_ports];
@ -1409,6 +1418,7 @@ LV2Plugin::allocate_atom_event_buffers()
*/ */
int count_atom_out = 0; int count_atom_out = 0;
int count_atom_in = 0; int count_atom_in = 0;
int minimumSize = 32768; // TODO use a per-port minimum-size
for (uint32_t i = 0; i < lilv_plugin_get_num_ports(p); ++i) { for (uint32_t i = 0; i < lilv_plugin_get_num_ports(p); ++i) {
const LilvPort* port = lilv_plugin_get_port_by_index(p, i); const LilvPort* port = lilv_plugin_get_port_by_index(p, i);
if (lilv_port_is_a(p, port, _world.atom_AtomPort)) { if (lilv_port_is_a(p, port, _world.atom_AtomPort)) {
@ -1425,6 +1435,10 @@ LV2Plugin::allocate_atom_event_buffers()
if (lilv_port_is_a(p, port, _world.lv2_OutputPort)) { if (lilv_port_is_a(p, port, _world.lv2_OutputPort)) {
count_atom_out++; count_atom_out++;
} }
LilvNode* min_size = lilv_port_get(_impl->plugin, port, _world.rsz_minimumSize);
if (min_size && lilv_node_is_int(min_size)) {
minimumSize = std::max(minimumSize, lilv_node_as_int(min_size));
}
} }
lilv_nodes_free(buffer_types); lilv_nodes_free(buffer_types);
lilv_nodes_free(atom_supports); lilv_nodes_free(atom_supports);
@ -1442,7 +1456,7 @@ LV2Plugin::allocate_atom_event_buffers()
DEBUG_TRACE(DEBUG::LV2, string_compose("allocate %1 atom_ev_buffers\n", total_atom_buffers)); DEBUG_TRACE(DEBUG::LV2, string_compose("allocate %1 atom_ev_buffers\n", total_atom_buffers));
_atom_ev_buffers = (LV2_Evbuf**) malloc((total_atom_buffers + 1) * sizeof(LV2_Evbuf*)); _atom_ev_buffers = (LV2_Evbuf**) malloc((total_atom_buffers + 1) * sizeof(LV2_Evbuf*));
for (int i = 0; i < total_atom_buffers; ++i ) { for (int i = 0; i < total_atom_buffers; ++i ) {
_atom_ev_buffers[i] = lv2_evbuf_new(32768, LV2_EVBUF_ATOM, _atom_ev_buffers[i] = lv2_evbuf_new(minimumSize, LV2_EVBUF_ATOM,
LV2Plugin::urids.atom_Chunk, LV2Plugin::urids.atom_Sequence); LV2Plugin::urids.atom_Chunk, LV2Plugin::urids.atom_Sequence);
} }
_atom_ev_buffers[total_atom_buffers] = 0; _atom_ev_buffers[total_atom_buffers] = 0;
@ -1551,6 +1565,12 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
index = out_map.get(DataType::MIDI, midi_out_index++, &valid); index = out_map.get(DataType::MIDI, midi_out_index++, &valid);
} }
if (valid && bufs.count().n_midi() > index) { 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( _ev_buffers[port_index] = bufs.get_lv2_midi(
(flags & PORT_INPUT), index, (flags & PORT_EVENT)); (flags & PORT_INPUT), index, (flags & PORT_EVENT));
} }
@ -1881,6 +1901,7 @@ LV2World::LV2World()
lv2_enumeration = lilv_new_uri(world, LV2_CORE__enumeration); lv2_enumeration = lilv_new_uri(world, LV2_CORE__enumeration);
midi_MidiEvent = lilv_new_uri(world, LILV_URI_MIDI_EVENT); midi_MidiEvent = lilv_new_uri(world, LILV_URI_MIDI_EVENT);
rdfs_comment = lilv_new_uri(world, LILV_NS_RDFS "comment"); rdfs_comment = lilv_new_uri(world, LILV_NS_RDFS "comment");
rsz_minimumSize = lilv_new_uri(world, LV2_RESIZE_PORT__minimumSize);
time_Position = lilv_new_uri(world, LV2_TIME__Position); time_Position = lilv_new_uri(world, LV2_TIME__Position);
ui_GtkUI = lilv_new_uri(world, LV2_UI__GtkUI); ui_GtkUI = lilv_new_uri(world, LV2_UI__GtkUI);
ui_external = lilv_new_uri(world, "http://lv2plug.in/ns/extensions/ui#external"); ui_external = lilv_new_uri(world, "http://lv2plug.in/ns/extensions/ui#external");
@ -1903,6 +1924,7 @@ LV2World::~LV2World()
lilv_node_free(ext_logarithmic); lilv_node_free(ext_logarithmic);
lilv_node_free(ext_notOnGUI); lilv_node_free(ext_notOnGUI);
lilv_node_free(ev_EventPort); lilv_node_free(ev_EventPort);
lilv_node_free(rsz_minimumSize);
lilv_node_free(atom_eventTransfer); lilv_node_free(atom_eventTransfer);
lilv_node_free(atom_bufferType); lilv_node_free(atom_bufferType);
lilv_node_free(atom_Sequence); lilv_node_free(atom_Sequence);