#include <cstdlib>
#include <cstring>
-#include <glib/gstdio.h>
+#include "pbd/gstdio_compat.h"
#include <glib/gprintf.h>
#include <glibmm.h>
LilvNode* units_midiNote;
LilvNode* patch_writable;
LilvNode* patch_Message;
+ LilvNode* lv2_noSampleAccurateCtrl;
#ifdef HAVE_LV2_1_2_0
LilvNode* bufz_powerOf2BlockLength;
LilvNode* bufz_fixedBlockLength;
struct LV2Plugin::Impl {
Impl() : plugin(0), ui(0), ui_type(0), name(0), author(0), instance(0)
, work_iface(0)
+#ifdef HAVE_LV2_1_2_0
, opts_iface(0)
+#endif
, state(0)
, block_length(0)
+#ifdef HAVE_LV2_1_2_0
+ , options(0)
+#endif
{}
/** Find the LV2 input port with the given designation.
LilvNode* author;
LilvInstance* instance;
const LV2_Worker_Interface* work_iface;
+#ifdef HAVE_LV2_1_2_0
const LV2_Options_Interface* opts_iface;
+#endif
LilvState* state;
LV2_Atom_Forge forge;
LV2_Atom_Forge ui_forge;
int32_t block_length;
+#ifdef HAVE_LV2_1_2_0
+ LV2_Options_Option* options;
+#endif
};
LV2Plugin::LV2Plugin (AudioEngine& engine,
, _patch_port_in_index((uint32_t)-1)
, _patch_port_out_index((uint32_t)-1)
, _uri_map(URIMap::instance())
+ , _no_sample_accurate_ctrl (false)
{
init(c_plugin, rate);
}
, _patch_port_in_index((uint32_t)-1)
, _patch_port_out_index((uint32_t)-1)
, _uri_map(URIMap::instance())
+ , _no_sample_accurate_ctrl (false)
{
init(other._impl->plugin, other._sample_rate);
{ LV2_OPTIONS_INSTANCE, 0, 0, 0, 0, NULL }
};
+ _impl->options = (LV2_Options_Option*) malloc (sizeof (options));
+ memcpy ((void*) _impl->options, (void*) options, sizeof (options));
+
_options_feature.URI = LV2_OPTIONS__options;
- _options_feature.data = options;
+ _options_feature.data = _impl->options;
_features[n_features++] = &_options_feature;
#endif
lilv_node_free(worker_iface_uri);
+#ifdef HAVE_LV2_1_2_0
LilvNode* options_iface_uri = lilv_new_uri(_world.world, LV2_OPTIONS__interface);
if (lilv_plugin_has_extension_data(plugin, options_iface_uri)) {
_impl->opts_iface = (const LV2_Options_Interface*)extension_data(
LV2_OPTIONS__interface);
}
lilv_node_free(options_iface_uri);
+#endif
if (lilv_plugin_has_feature(plugin, _world.lv2_inPlaceBroken)) {
error << string_compose(
throw failed_constructor();
}
lilv_nodes_free(required_features);
+
+ LilvNodes* optional_features = lilv_plugin_get_optional_features (plugin);
+ if (lilv_nodes_contains (optional_features, _world.lv2_noSampleAccurateCtrl)) {
+ _no_sample_accurate_ctrl = true;
+ }
+ lilv_nodes_free(optional_features);
#endif
#ifdef HAVE_LILV_0_16_0
if (state && _has_state_interface) {
lilv_state_restore(state, _impl->instance, NULL, NULL, 0, NULL);
}
+ lilv_state_free(state);
#endif
_sample_rate = rate;
return 0;
}
+bool
+LV2Plugin::requires_fixed_sized_buffers () const
+{
+ /* This controls if Ardour will split the plugin's run()
+ * on automation events in order to pass sample-accurate automation
+ * via standard control-ports.
+ *
+ * When returning true Ardour will *not* sub-divide the process-cycle.
+ * Automation events that happen between cycle-start and cycle-end will be
+ * ignored (ctrl values are interpolated to cycle-start).
+ * NB. Atom Sequences are still sample accurate.
+ *
+ * Note: This does not guarantee a fixed block-size.
+ * e.g The process cycle may be split when looping, also
+ * the period-size may change any time: see set_block_size()
+ */
+ return _no_sample_accurate_ctrl;
+}
+
LV2Plugin::~LV2Plugin ()
{
DEBUG_TRACE(DEBUG::LV2, string_compose("%1 destroy\n", name()));
cleanup();
lilv_instance_free(_impl->instance);
+ lilv_state_free(_impl->state);
lilv_node_free(_impl->name);
lilv_node_free(_impl->author);
+#ifdef HAVE_LV2_1_2_0
+ free(_impl->options);
+#endif
free(_features);
free(_make_path_feature.data);
delete [] _control_data;
delete [] _shadow_data;
+ delete [] _defaults;
delete [] _ev_buffers;
}
assert(_insert_id != PBD::ID("0"));
XMLNode* child;
- char buf[16];
+ char buf[32];
LocaleGuard lg(X_("C"));
for (uint32_t i = 0; i < parameter_count(); ++i) {
_world.world, _uri_map.urid_map(), NULL, state_file.c_str());
lilv_state_restore(state, _impl->instance, NULL, NULL, 0, NULL);
+ lilv_state_free(_impl->state);
+ _impl->state = state;
}
latency_compute_run();
static bool lv2_filter (const string& str, void* /*arg*/)
{
/* Not a dotfile, has a prefix before a period, suffix is "lv2" */
-
+
return str[0] != '.' && (str.length() > 3 && str.find (".lv2") == (str.length() - 4));
}
units_db = lilv_new_uri(world, LV2_UNITS__db);
patch_writable = lilv_new_uri(world, LV2_PATCH__writable);
patch_Message = lilv_new_uri(world, LV2_PATCH__Message);
+ lv2_noSampleAccurateCtrl = lilv_new_uri(world, LV2_CORE_PREFIX "NoSampleAccurateCtrl"); // XXX
#ifdef HAVE_LV2_1_2_0
bufz_powerOf2BlockLength = lilv_new_uri(world, LV2_BUF_SIZE__powerOf2BlockLength);
bufz_fixedBlockLength = lilv_new_uri(world, LV2_BUF_SIZE__fixedBlockLength);
lilv_node_free(bufz_fixedBlockLength);
lilv_node_free(bufz_powerOf2BlockLength);
#endif
+ lilv_node_free(lv2_noSampleAccurateCtrl);
lilv_node_free(patch_Message);
lilv_node_free(patch_writable);
lilv_node_free(units_hz);
return PluginPtr();
}
+bool
+LV2PluginInfo::in_category (const std::string &c) const
+{
+ // TODO use untranslated lilv_plugin_get_class()
+ // match gtk2_ardour/plugin_selector.cc
+ if (category == c) {
+ return true;
+ }
+ return false;
+}
+
PluginInfoList*
LV2PluginInfo::discover()
{