Compare commits

...

2 Commits

Author SHA1 Message Date
David Robillard c4f8a01ff0 WIP: Remove support for deprecated LV2 event extension
Not tested whatsoever, don't merge this.
2020-11-22 18:56:42 +01:00
David Robillard c12cabd418 Remove support for the long-deprecated LV2 uri-map extension
This has been supplanted by the urid extension.
2020-11-22 18:56:42 +01:00
8 changed files with 71 additions and 232 deletions

View File

@ -115,10 +115,9 @@ public:
/** Get a MIDI buffer translated into an LV2 MIDI buffer for use with
* plugins. The index here corresponds directly to MIDI buffer numbers
* (i.e. the index passed to get_midi), translation back and forth will
* happen as needed. If old_api is true, the returned buffer will be in
* old event format. Otherwise it will be in new atom sequence format.
* happen as needed.
*/
LV2_Evbuf* get_lv2_midi(bool input, size_t i, bool old_api);
LV2_Evbuf* get_lv2_midi(bool input, size_t i);
/** ensure minimum size of LV2 Atom port buffer */
void ensure_lv2_bufsize(bool input, size_t i, size_t buffer_capacity);

View File

@ -125,7 +125,6 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
bool parameter_is_audio (uint32_t) const;
bool parameter_is_control (uint32_t) const;
bool parameter_is_event (uint32_t) const;
bool parameter_is_input (uint32_t) const;
bool parameter_is_output (uint32_t) const;
bool parameter_is_toggled (uint32_t) const;
@ -242,7 +241,6 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
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

View File

@ -28,14 +28,13 @@
#include <glibmm/threads.h>
#include "lv2.h"
#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h"
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
#include "ardour/libardour_visibility.h"
namespace ARDOUR {
/** Implementation of the LV2 uri-map and urid extensions.
/** Implementation of the LV2 urid extension.
*
* This just uses a pair of std::map and is not so great in the space overhead
* department, but it's fast enough and not really performance critical anyway.
@ -46,7 +45,6 @@ public:
URIMap();
LV2_Feature* uri_map_feature() { return &_uri_map_feature; }
LV2_Feature* urid_map_feature() { return &_urid_map_feature; }
LV2_Feature* urid_unmap_feature() { return &_urid_unmap_feature; }
@ -107,8 +105,6 @@ private:
Map _map;
Unmap _unmap;
LV2_Feature _uri_map_feature;
LV2_URI_Map_Feature _uri_map_feature_data;
LV2_Feature _urid_map_feature;
LV2_URID_Map _urid_map_feature_data;
LV2_Feature _urid_unmap_feature;

View File

@ -197,7 +197,6 @@ BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capac
while (_lv2_buffers.size() < _buffers[type].size() * 2) {
_lv2_buffers.push_back(
std::make_pair(false, lv2_evbuf_new(buffer_capacity,
LV2_EVBUF_EVENT,
URIMap::instance().urids.atom_Chunk,
URIMap::instance().urids.atom_Sequence)));
}
@ -269,20 +268,18 @@ BufferSet::ensure_lv2_bufsize(bool input, size_t i, size_t buffer_capacity)
_lv2_buffers.at(i * 2 + (input ? 0 : 1)) =
std::make_pair(false, lv2_evbuf_new(
buffer_capacity,
LV2_EVBUF_EVENT,
URIMap::instance().urids.atom_Chunk,
URIMap::instance().urids.atom_Sequence));
}
LV2_Evbuf*
BufferSet::get_lv2_midi(bool input, size_t i, bool old_api)
BufferSet::get_lv2_midi(bool input, size_t i)
{
assert(count().get(DataType::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_reset(evbuf, input);
return evbuf;
}

View File

@ -24,14 +24,10 @@
#include "lv2_evbuf.h"
struct LV2_Evbuf_Impl {
LV2_Evbuf_Type type;
uint32_t capacity;
uint32_t atom_Chunk;
uint32_t atom_Sequence;
union {
LV2_Event_Buffer event;
LV2_Atom_Sequence atom;
} buf;
uint32_t capacity;
uint32_t atom_Chunk;
uint32_t atom_Sequence;
LV2_Atom_Sequence atom;
};
static inline uint32_t
@ -42,7 +38,6 @@ lv2_evbuf_pad_size(uint32_t size)
LV2_Evbuf*
lv2_evbuf_new(uint32_t capacity,
LV2_Evbuf_Type type,
uint32_t atom_Chunk,
uint32_t atom_Sequence)
{
@ -52,7 +47,6 @@ lv2_evbuf_new(uint32_t capacity,
evbuf->capacity = capacity;
evbuf->atom_Chunk = atom_Chunk;
evbuf->atom_Sequence = atom_Sequence;
lv2_evbuf_set_type(evbuf, type);
lv2_evbuf_reset(evbuf, true);
return evbuf;
}
@ -63,56 +57,27 @@ lv2_evbuf_free(LV2_Evbuf* evbuf)
free(evbuf);
}
void
lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type)
{
evbuf->type = type;
switch (type) {
case LV2_EVBUF_EVENT:
evbuf->buf.event.data = (uint8_t*)(evbuf + 1);
evbuf->buf.event.capacity = evbuf->capacity;
break;
case LV2_EVBUF_ATOM:
break;
}
lv2_evbuf_reset(evbuf, true);
}
void
lv2_evbuf_reset(LV2_Evbuf* evbuf, bool input)
{
switch (evbuf->type) {
case LV2_EVBUF_EVENT:
evbuf->buf.event.header_size = sizeof(LV2_Event_Buffer);
evbuf->buf.event.stamp_type = LV2_EVENT_AUDIO_STAMP;
evbuf->buf.event.event_count = 0;
evbuf->buf.event.size = 0;
break;
case LV2_EVBUF_ATOM:
if (input) {
evbuf->buf.atom.atom.size = sizeof(LV2_Atom_Sequence_Body);
evbuf->buf.atom.atom.type = evbuf->atom_Sequence;
} else {
evbuf->buf.atom.atom.size = evbuf->capacity;
evbuf->buf.atom.atom.type = evbuf->atom_Chunk;
}
if (input) {
evbuf->atom.atom.size = sizeof(LV2_Atom_Sequence_Body);
evbuf->atom.atom.type = evbuf->atom_Sequence;
} else {
evbuf->atom.atom.size = evbuf->capacity;
evbuf->atom.atom.type = evbuf->atom_Chunk;
}
}
uint32_t
lv2_evbuf_get_size(LV2_Evbuf* evbuf)
{
switch (evbuf->type) {
case LV2_EVBUF_EVENT:
return evbuf->buf.event.size;
case LV2_EVBUF_ATOM:
assert(evbuf->buf.atom.atom.type != evbuf->atom_Sequence
|| evbuf->buf.atom.atom.size >= sizeof(LV2_Atom_Sequence_Body));
return evbuf->buf.atom.atom.type == evbuf->atom_Sequence
? evbuf->buf.atom.atom.size - sizeof(LV2_Atom_Sequence_Body)
: 0;
}
return 0;
assert(evbuf->atom.atom.type != evbuf->atom_Sequence
|| evbuf->atom.atom.size >= sizeof(LV2_Atom_Sequence_Body));
return evbuf->atom.atom.type == evbuf->atom_Sequence
? evbuf->atom.atom.size - sizeof(LV2_Atom_Sequence_Body)
: 0;
}
uint32_t
@ -124,13 +89,7 @@ lv2_evbuf_get_capacity(LV2_Evbuf* evbuf)
void*
lv2_evbuf_get_buffer(LV2_Evbuf* evbuf)
{
switch (evbuf->type) {
case LV2_EVBUF_EVENT:
return &evbuf->buf.event;
case LV2_EVBUF_ATOM:
return &evbuf->buf.atom;
}
return NULL;
return &evbuf->atom;
}
LV2_Evbuf_Iterator
@ -163,19 +122,13 @@ lv2_evbuf_next(LV2_Evbuf_Iterator iter)
LV2_Evbuf* evbuf = iter.evbuf;
uint32_t offset = iter.offset;
uint32_t size;
switch (evbuf->type) {
case LV2_EVBUF_EVENT:
size = ((LV2_Event*)((uintptr_t)(evbuf->buf.event.data + offset)))->size;
offset += lv2_evbuf_pad_size(sizeof(LV2_Event) + size);
break;
case LV2_EVBUF_ATOM:
size = ((LV2_Atom_Event*)((uintptr_t)
((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, &evbuf->buf.atom)
+ offset)))->body.size;
offset += lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
break;
}
uint32_t size =
((LV2_Atom_Event*)((uintptr_t)(
(char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, &evbuf->atom) +
offset)))
->body.size;
offset += lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
LV2_Evbuf_Iterator next = { evbuf, offset };
return next;
@ -196,32 +149,15 @@ lv2_evbuf_get(LV2_Evbuf_Iterator iter,
return false;
}
LV2_Event_Buffer* ebuf;
LV2_Event* ev;
LV2_Atom_Sequence* aseq;
LV2_Atom_Event* aev;
switch (iter.evbuf->type) {
case LV2_EVBUF_EVENT:
ebuf = &iter.evbuf->buf.event;
ev = (LV2_Event*)((uintptr_t)((char*)ebuf->data + iter.offset));
*samples = ev->frames;
*subframes = ev->subframes;
*type = ev->type;
*size = ev->size;
*data = (uint8_t*)ev + sizeof(LV2_Event);
break;
case LV2_EVBUF_ATOM:
aseq = (LV2_Atom_Sequence*)&iter.evbuf->buf.atom;
aev = (LV2_Atom_Event*)((uintptr_t)(
(char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq)
+ iter.offset));
*samples = aev->time.frames;
*subframes = 0;
*type = aev->body.type;
*size = aev->body.size;
*data = (uint8_t*)LV2_ATOM_BODY(&aev->body);
break;
}
LV2_Atom_Sequence* aseq = (LV2_Atom_Sequence*)&iter.evbuf->atom;
LV2_Atom_Event* aev = (LV2_Atom_Event*)((uintptr_t)(
(char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq) + iter.offset));
*samples = aev->time.frames;
*subframes = 0;
*type = aev->body.type;
*size = aev->body.size;
*data = (uint8_t*)LV2_ATOM_BODY(&aev->body);
return true;
}
@ -234,51 +170,24 @@ lv2_evbuf_write(LV2_Evbuf_Iterator* iter,
uint32_t size,
const uint8_t* data)
{
LV2_Event_Buffer* ebuf;
LV2_Event* ev;
LV2_Atom_Sequence* aseq;
LV2_Atom_Event* aev;
switch (iter->evbuf->type) {
case LV2_EVBUF_EVENT:
ebuf = &iter->evbuf->buf.event;
if (ebuf->capacity - ebuf->size < sizeof(LV2_Event) + size) {
return false;
}
LV2_Atom_Sequence* aseq = (LV2_Atom_Sequence*)&iter->evbuf->atom;
ev = (LV2_Event*)((uintptr_t)(ebuf->data + iter->offset));
ev->frames = samples;
ev->subframes = subframes;
ev->type = type;
ev->size = size;
memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size);
size = lv2_evbuf_pad_size(sizeof(LV2_Event) + size);
ebuf->size += size;
ebuf->event_count += 1;
iter->offset += size;
break;
case LV2_EVBUF_ATOM:
aseq = (LV2_Atom_Sequence*)&iter->evbuf->buf.atom;
if (iter->evbuf->capacity - sizeof(LV2_Atom) - aseq->atom.size
< sizeof(LV2_Atom_Event) + size) {
return false;
}
aev = (LV2_Atom_Event*)((uintptr_t)(
(char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq)
+ iter->offset));
aev->time.frames = samples;
aev->body.type = type;
aev->body.size = size;
memcpy(LV2_ATOM_BODY(&aev->body), data, size);
size = lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
aseq->atom.size += size;
iter->offset += size;
break;
default:
if (iter->evbuf->capacity - sizeof(LV2_Atom) - aseq->atom.size
< sizeof(LV2_Atom_Event) + size) {
return false;
}
LV2_Atom_Event* aev = (LV2_Atom_Event*)((uintptr_t)(
(char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq) + iter->offset));
aev->time.frames = samples;
aev->body.type = type;
aev->body.size = size;
memcpy(LV2_ATOM_BODY(&aev->body), data, size);
size = lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
aseq->atom.size += size;
iter->offset += size;
return true;
}

View File

@ -25,21 +25,6 @@ extern "C" {
#include <stdbool.h>
#endif
/**
Format of actual buffer.
*/
typedef enum {
/**
An (old) ev:EventBuffer (LV2_Event_Buffer).
*/
LV2_EVBUF_EVENT,
/**
A (new) atom:Sequence (LV2_Atom_Sequence).
*/
LV2_EVBUF_ATOM
} LV2_Evbuf_Type;
/**
An abstract/opaque LV2 event buffer.
*/
@ -58,10 +43,9 @@ typedef struct {
URIDs for atom:Chunk and atom:Sequence must be passed for LV2_EVBUF_ATOM.
*/
LV2_Evbuf*
lv2_evbuf_new(uint32_t capacity,
LV2_Evbuf_Type type,
uint32_t atom_Chunk,
uint32_t atom_Sequence);
lv2_evbuf_new(uint32_t capacity,
uint32_t atom_Chunk,
uint32_t atom_Sequence);
/**
Free an event buffer allocated with lv2_evbuf_new.
@ -69,13 +53,6 @@ lv2_evbuf_new(uint32_t capacity,
void
lv2_evbuf_free(LV2_Evbuf* evbuf);
/**
Reset and change the type of an existing event buffer.
URIDs for atom:Chunk and atom:Sequence must be passed for LV2_EVBUF_ATOM.
*/
void
lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type);
/**
Clear and initialize an existing event buffer.
The contents of buf are ignored entirely and overwritten, except capacity

View File

@ -496,12 +496,11 @@ LV2Plugin::init(const void* c_plugin, samplecnt_t rate)
_features[0] = &_instance_access_feature;
_features[1] = &_data_access_feature;
_features[2] = &_make_path_feature;
_features[3] = _uri_map.uri_map_feature();
_features[4] = _uri_map.urid_map_feature();
_features[5] = _uri_map.urid_unmap_feature();
_features[6] = &_log_feature;
_features[3] = _uri_map.urid_map_feature();
_features[4] = _uri_map.urid_unmap_feature();
_features[5] = &_log_feature;
unsigned n_features = 7;
unsigned n_features = 6;
_features[n_features++] = &_def_state_feature;
lv2_atom_forge_init(&_impl->forge, _uri_map.urid_map());
@ -723,9 +722,6 @@ LV2Plugin::init(const void* c_plugin, samplecnt_t rate)
flags |= PORT_CONTROL;
} else if (lilv_port_is_a(_impl->plugin, port, _world.lv2_AudioPort)) {
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);
@ -2335,7 +2331,7 @@ LV2Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
match = PORT_AUDIO;
break;
case DataType::MIDI:
match = PORT_SEQUENCE | PORT_MIDI; // ignore old PORT_EVENT
match = PORT_SEQUENCE | PORT_MIDI;
break;
default:
return Plugin::IOPortDescription ("?");
@ -2595,8 +2591,9 @@ LV2Plugin::allocate_atom_event_buffers()
DEBUG_TRACE(DEBUG::LV2, string_compose("allocate %1 atom_ev_buffers of %2 bytes\n", total_atom_buffers, minimumSize));
_atom_ev_buffers = (LV2_Evbuf**) malloc((total_atom_buffers + 1) * sizeof(LV2_Evbuf*));
for (int i = 0; i < total_atom_buffers; ++i ) {
_atom_ev_buffers[i] = lv2_evbuf_new(minimumSize, LV2_EVBUF_ATOM,
_uri_map.urids.atom_Chunk, _uri_map.urids.atom_Sequence);
_atom_ev_buffers[i] = lv2_evbuf_new(minimumSize,
_uri_map.urids.atom_Chunk,
_uri_map.urids.atom_Sequence);
}
_atom_ev_buffers[total_atom_buffers] = 0;
return;
@ -2741,7 +2738,7 @@ 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_SEQUENCE)) {
} else if (flags & 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...
@ -2760,7 +2757,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
*/
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));
(flags & PORT_INPUT), index);
}
} else if ((flags & PORT_POSITION) && (flags & PORT_INPUT)) {
lv2_evbuf_reset(_atom_ev_buffers[atom_port_index], true);
@ -2830,7 +2827,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
scratch_bufs.ensure_lv2_bufsize((flags & PORT_INPUT),
0, _port_minimumSize[port_index]);
_ev_buffers[port_index] = scratch_bufs.get_lv2_midi(
(flags & PORT_INPUT), 0, (flags & PORT_EVENT));
(flags & PORT_INPUT), 0);
}
buf = lv2_evbuf_get_buffer(_ev_buffers[port_index]);
@ -2867,7 +2864,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
*/
else if (atom->type == _uri_map.urids.atom_Blank ||
atom->type == _uri_map.urids.atom_Object) {
LV2_Atom_Object* obj = (LV2_Atom_Object*)atom;
const LV2_Atom_Object* obj = (const LV2_Atom_Object*)atom;
if (obj->body.otype == _uri_map.urids.patch_Set) {
const LV2_Atom* property = NULL;
const LV2_Atom* value = NULL;
@ -2912,7 +2909,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
* for quite a while at least ;)
*/
// copy output of LV2 plugin's MIDI port to Ardour MIDI buffers -- MIDI OUT
if ((flags & PORT_OUTPUT) && (flags & (PORT_EVENT|PORT_SEQUENCE|PORT_MIDI))) {
if ((flags & PORT_OUTPUT) && (flags & (PORT_SEQUENCE|PORT_MIDI))) {
const uint32_t buf_index = out_map.get(
DataType::MIDI, midi_out_index++, &valid);
if (valid) {
@ -2920,7 +2917,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
}
}
// Flush MIDI (write back to Ardour MIDI buffers) -- MIDI THRU
else if ((flags & PORT_OUTPUT) && (flags & (PORT_EVENT|PORT_SEQUENCE))) {
else if ((flags & PORT_OUTPUT) && (flags & PORT_SEQUENCE)) {
const uint32_t buf_index = out_map.get(
DataType::MIDI, midi_out_index++, &valid);
if (valid) {
@ -2930,7 +2927,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
// Write messages to UI
if ((_to_ui || _can_write_automation || _patch_port_out_index != (uint32_t)-1) &&
(flags & PORT_OUTPUT) && (flags & (PORT_EVENT|PORT_SEQUENCE))) {
(flags & PORT_OUTPUT) && (flags & PORT_SEQUENCE)) {
LV2_Evbuf* buf = _ev_buffers[port_index];
for (LV2_Evbuf_Iterator i = lv2_evbuf_begin(buf);
lv2_evbuf_is_valid(i);
@ -3083,7 +3080,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
_property_values[prop_id] = Variant(Variant::PATH, path);
}
if (value->type == _uri_map.urids.atom_Float) {
const float* val = (float*)LV2_ATOM_BODY_CONST(value);
const float* val = (const float*)LV2_ATOM_BODY_CONST(value);
_property_values[prop_id] = Variant(Variant::FLOAT, *val);
}
// TODO add support for other props (Int, Bool, ..)
@ -3152,13 +3149,6 @@ LV2Plugin::parameter_is_audio(uint32_t param) const
return _port_flags[param] & PORT_AUDIO;
}
bool
LV2Plugin::parameter_is_event(uint32_t param) const
{
assert(param < _port_flags.size());
return _port_flags[param] & PORT_EVENT;
}
bool
LV2Plugin::parameter_is_output(uint32_t param) const
{

View File

@ -85,28 +85,6 @@ URIMap::instance()
return *URIMap::uri_map;
}
static uint32_t
c_uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data,
const char* map,
const char* uri)
{
URIMap* const me = (URIMap*)callback_data;
const uint32_t id = me->uri_to_id(uri);
/* The event context with the uri-map extension guarantees a value in the
range of uint16_t. Ardour used to map to a separate range to achieve
this, but unfortunately some plugins are broken and use the incorrect
context. To compensate, we simply use the same context for everything
and hope that anything in the event context gets mapped before
UINT16_MAX is reached (which will be fine unless something seriously
weird is going on). If this fails there is nothing we can do, die.
*/
assert(!map || strcmp(map, "http://lv2plug.in/ns/ext/event")
|| id < UINT16_MAX);
return id;
}
static LV2_URID
c_urid_map(LV2_URID_Map_Handle handle,
const char* uri)
@ -125,11 +103,6 @@ c_urid_unmap(LV2_URID_Unmap_Handle handle,
URIMap::URIMap()
{
_uri_map_feature_data.uri_to_id = c_uri_map_uri_to_id;
_uri_map_feature_data.callback_data = this;
_uri_map_feature.URI = LV2_URI_MAP_URI;
_uri_map_feature.data = &_uri_map_feature_data;
_urid_map_feature_data.map = c_urid_map;
_urid_map_feature_data.handle = this;
_urid_map_feature.URI = LV2_URID_MAP_URI;