X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Flv2_plugin.cc;h=4c3ca31d2dca53d1e3263fcdde2adbc7babe1486;hb=e0ff70cf86c01c42f98faf8b0eaf1a8ccf867946;hp=1f0e20f779fed485261f88f5faa1ba01ddee5ecd;hpb=93bc9b972888f5a8c08115eccb66a35d4f3853a6;p=ardour.git diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 1f0e20f779..4c3ca31d2d 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -132,6 +132,7 @@ public: LilvNode* lv2_enumeration; LilvNode* lv2_freewheeling; LilvNode* lv2_inPlaceBroken; + LilvNode* lv2_isSideChain; LilvNode* lv2_integer; LilvNode* lv2_default; LilvNode* lv2_minimum; @@ -216,6 +217,7 @@ work_respond(LV2_Worker_Respond_Handle handle, } } +#ifdef LV2_EXTENDED /* inline display extension */ static void queue_draw (LV2_Inline_Display_Handle handle) @@ -223,6 +225,7 @@ queue_draw (LV2_Inline_Display_Handle handle) LV2Plugin* plugin = (LV2Plugin*)handle; plugin->QueueDraw(); /* EMIT SIGNAL */ } +#endif /* log extension */ @@ -362,6 +365,8 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) _was_activated = false; _has_state_interface = false; _can_write_automation = false; + _max_latency = 0; + _current_latency = 0; _impl->block_length = _session.get_block_size(); _instance_access_feature.URI = "http://lv2plug.in/ns/ext/instance-access"; @@ -629,6 +634,7 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) _port_flags.push_back(flags); _port_minimumSize.push_back(minimumSize); + DEBUG_TRACE(DEBUG::LV2, string_compose("port %1 buffer %2 bytes\n", i, minimumSize)); } _control_data = new float[num_ports]; @@ -670,6 +676,9 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) lilv_instance_connect_port(_impl->instance, i, &_control_data[i]); if (latent && i == latency_index) { + LilvNode *max; + lilv_port_get_range(_impl->plugin, port, NULL, NULL, &max); + _max_latency = max ? lilv_node_as_float(max) : .02 * _sample_rate; _latency_control_port = &_control_data[i]; *_latency_control_port = 0; } @@ -800,6 +809,7 @@ LV2Plugin::~LV2Plugin () #endif free(_features); + free(_log_feature.data); free(_make_path_feature.data); free(_work_schedule_feature.data); @@ -820,6 +830,7 @@ LV2Plugin::~LV2Plugin () delete [] _shadow_data; delete [] _defaults; delete [] _ev_buffers; + delete _impl; } bool @@ -1116,7 +1127,7 @@ LV2Plugin::add_state(XMLNode* root) const XMLNode* child; char buf[32]; - LocaleGuard lg(X_("C")); + LocaleGuard lg; for (uint32_t i = 0; i < parameter_count(); ++i) { if (parameter_is_input(i) && parameter_is_control(i)) { @@ -1789,13 +1800,13 @@ int LV2Plugin::set_state(const XMLNode& node, int version) { XMLNodeList nodes; - const XMLProperty* prop; + XMLProperty const * prop; XMLNodeConstIterator iter; XMLNode* child; const char* sym; const char* value; uint32_t port_id; - LocaleGuard lg(X_("C")); + LocaleGuard lg; if (node.name() != state_node_name()) { error << _("Bad node sent to LV2Plugin::set_state") << endmsg; @@ -1925,6 +1936,56 @@ LV2Plugin::get_parameter_descriptor(uint32_t which, ParameterDescriptor& desc) c return 0; } +Plugin::IOPortDescription +LV2Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const +{ + PortFlags match = 0; + switch (dt) { + case DataType::AUDIO: + match = PORT_AUDIO; + break; + case DataType::MIDI: + match = PORT_SEQUENCE | PORT_MIDI; // ignore old PORT_EVENT + break; + default: + return Plugin::IOPortDescription ("?"); + break; + } + if (input) { + match |= PORT_INPUT; + } else { + match |= PORT_OUTPUT; + } + + uint32_t p = 0; + uint32_t idx = UINT32_MAX; + + uint32_t const num_ports = parameter_count(); + for (uint32_t port_index = 0; port_index < num_ports; ++port_index) { + PortFlags flags = _port_flags[port_index]; + if ((flags & match) == match) { + if (p == id) { + idx = port_index; + } + ++p; + } + } + if (idx == UINT32_MAX) { + return Plugin::IOPortDescription ("?"); + } + + LilvNode* name = lilv_port_get_name(_impl->plugin, + lilv_plugin_get_port_by_index(_impl->plugin, idx)); + Plugin::IOPortDescription iod (lilv_node_as_string (name)); + lilv_node_free(name); + + if (lilv_port_has_property(_impl->plugin, + lilv_plugin_get_port_by_index(_impl->plugin, idx), _world.lv2_isSideChain)) { + iod.is_sidechain = true; + } + return iod; +} + string LV2Plugin::describe_parameter(Evoral::Parameter which) { @@ -1955,6 +2016,12 @@ LV2Plugin::describe_parameter(Evoral::Parameter which) } } +framecnt_t +LV2Plugin::max_latency () const +{ + return _max_latency; +} + framecnt_t LV2Plugin::signal_latency() const { @@ -2053,8 +2120,7 @@ LV2Plugin::allocate_atom_event_buffers() LilvNodes* atom_supports = lilv_port_get_value( p, port, _world.atom_supports); - if (!lilv_nodes_contains(buffer_types, _world.atom_Sequence) - || !lilv_nodes_contains(atom_supports, _world.midi_MidiEvent)) { + if (lilv_nodes_contains(buffer_types, _world.atom_Sequence)) { if (lilv_port_is_a(p, port, _world.lv2_InputPort)) { count_atom_in++; } @@ -2081,7 +2147,7 @@ LV2Plugin::allocate_atom_event_buffers() return; } - DEBUG_TRACE(DEBUG::LV2, string_compose("allocate %1 atom_ev_buffers of %d bytes\n", total_atom_buffers, minimumSize)); + 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, @@ -2244,7 +2310,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs, if (_session.transport_frame() != _next_cycle_start || _session.transport_speed() != _next_cycle_speed) { // Transport has changed, write position at cycle start - tmap.bbt_time(_session.transport_frame(), bbt); + bbt = tmap.bbt_at_frame (_session.transport_frame()); write_position(&_impl->forge, _ev_buffers[port_index], tmetric, bbt, _session.transport_speed(), _session.transport_frame(), 0); @@ -2276,7 +2342,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs, ++m; } else { tmetric.set_metric(metric); - bbt = metric->start(); + bbt = tmap.bbt_at_pulse (metric->pulse()); write_position(&_impl->forge, _ev_buffers[port_index], tmetric, bbt, _session.transport_speed(), metric->frame(), @@ -2462,19 +2528,18 @@ LV2Plugin::connect_and_run(BufferSet& bufs, _uri_map.urids.patch_value, &value, 0); - if (!property || !value || - property->type != _uri_map.urids.atom_URID || - value->type != _uri_map.urids.atom_Path) { + if (property && value && + property->type == _uri_map.urids.atom_URID && + value->type == _uri_map.urids.atom_Path) { + const uint32_t prop_id = ((const LV2_Atom_URID*)property)->body; + const char* path = (const char*)LV2_ATOM_BODY_CONST(value); + + // Emit PropertyChanged signal for UI + // TODO: This should emit the control's Changed signal + PropertyChanged(prop_id, Variant(Variant::PATH, path)); + } else { std::cerr << "warning: patch:Set for unknown property" << std::endl; - continue; } - - const uint32_t prop_id = ((const LV2_Atom_URID*)property)->body; - const char* path = (const char*)LV2_ATOM_BODY_CONST(value); - - // Emit PropertyChanged signal for UI - // TODO: This should emit the control's Changed signal - PropertyChanged(prop_id, Variant(Variant::PATH, path)); } } } @@ -2494,6 +2559,13 @@ LV2Plugin::connect_and_run(BufferSet& bufs, _next_cycle_speed = _session.transport_speed(); _next_cycle_start = _session.transport_frame() + (nframes * _next_cycle_speed); + if (_latency_control_port) { + framecnt_t new_latency = signal_latency (); + if (_current_latency != new_latency) { + LatencyChanged (_current_latency, new_latency); /* EMIT SIGNAL */ + } + _current_latency = new_latency; + } return 0; } @@ -2678,6 +2750,7 @@ LV2World::LV2World() lv2_InputPort = lilv_new_uri(world, LILV_URI_INPUT_PORT); lv2_OutputPort = lilv_new_uri(world, LILV_URI_OUTPUT_PORT); lv2_inPlaceBroken = lilv_new_uri(world, LV2_CORE__inPlaceBroken); + lv2_isSideChain = lilv_new_uri(world, LV2_CORE_PREFIX "isSideChain"); lv2_integer = lilv_new_uri(world, LV2_CORE__integer); lv2_default = lilv_new_uri(world, LV2_CORE__default); lv2_minimum = lilv_new_uri(world, LV2_CORE__minimum); @@ -2704,7 +2777,7 @@ LV2World::LV2World() patch_writable = lilv_new_uri(world, LV2_PATCH__writable); patch_Message = lilv_new_uri(world, LV2_PATCH__Message); #ifdef LV2_EXTENDED - lv2_noSampleAccurateCtrl = lilv_new_uri(world, LV2_CORE_PREFIX "noSampleAccurateControls"); + lv2_noSampleAccurateCtrl = lilv_new_uri(world, "http://ardour.org/lv2/ext#noSampleAccurateControls"); auto_can_write_automatation = lilv_new_uri(world, LV2_AUTOMATE_URI__can_write); auto_automation_control = lilv_new_uri(world, LV2_AUTOMATE_URI__control); auto_automation_controlled = lilv_new_uri(world, LV2_AUTOMATE_URI__controlled); @@ -2755,6 +2828,7 @@ LV2World::~LV2World() lilv_node_free(lv2_sampleRate); lilv_node_free(lv2_reportsLatency); lilv_node_free(lv2_integer); + lilv_node_free(lv2_isSideChain); lilv_node_free(lv2_inPlaceBroken); lilv_node_free(lv2_OutputPort); lilv_node_free(lv2_InputPort);