#include "pbd/stl_delete.h"
#include "pbd/compose.h"
#include "pbd/error.h"
+#include "pbd/replace_all.h"
#include "pbd/xml++.h"
#include "libardour-config.h"
#include "ardour/worker.h"
#include "ardour/search_paths.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
#include <locale.h>
#include <lilv/lilv.h>
LilvNode* ext_expensive;
LilvNode* ext_causesArtifacts;
LilvNode* ext_notAutomatic;
+ LilvNode* ext_rangeSteps;
LilvNode* lv2_AudioPort;
LilvNode* lv2_ControlPort;
LilvNode* lv2_InputPort;
return "";
}
+bool
+LV2Plugin::get_layout (uint32_t which, UILayoutHint& h) const
+{
+ /// TODO lookup port-properties
+ if (unique_id () != "urn:ardour:a-eq") {
+ return false;
+ }
+ h.knob = true;
+ switch (which) {
+ case 0: h.x0 = 0; h.x1 = 1; h.y0 = 2; h.y1 = 3; break; // Frequency L
+ case 1: h.x0 = 0; h.x1 = 1; h.y0 = 0; h.y1 = 1; break; // Gain L
+ case 17: h.x0 = 0; h.x1 = 1; h.y0 = 5; h.y1 = 6; break; // enable L
+
+ case 2: h.x0 = 1; h.x1 = 3; h.y0 = 2; h.y1 = 3; break; // Frequency 1
+ case 3: h.x0 = 1; h.x1 = 3; h.y0 = 0; h.y1 = 1; break; // Gain 1
+ case 4: h.x0 = 2; h.x1 = 4; h.y0 = 1; h.y1 = 2; break; // Bandwidth 1
+ case 18: h.x0 = 1; h.x1 = 4; h.y0 = 5; h.y1 = 6; break; // enable 1
+
+ case 5: h.x0 = 4; h.x1 = 6; h.y0 = 2; h.y1 = 3; break; // Frequency 2
+ case 6: h.x0 = 4; h.x1 = 6; h.y0 = 0; h.y1 = 1; break; // Gain 2
+ case 7: h.x0 = 5; h.x1 = 7; h.y0 = 1; h.y1 = 2; break; // Bandwidth 2
+ case 19: h.x0 = 4; h.x1 = 7; h.y0 = 5; h.y1 = 6; break; // enable 2
+
+ case 8: h.x0 = 7; h.x1 = 9; h.y0 = 2; h.y1 = 3; break; // Frequency 3
+ case 9: h.x0 = 7; h.x1 = 9; h.y0 = 0; h.y1 = 1; break; // Gain 3
+ case 10: h.x0 = 8; h.x1 = 10; h.y0 = 1; h.y1 = 2; break; // Bandwidth 3
+ case 20: h.x0 = 7; h.x1 = 10; h.y0 = 5; h.y1 = 6; break; // enable 3
+
+ case 11: h.x0 = 10; h.x1 = 12; h.y0 = 2; h.y1 = 3; break; // Frequency 4
+ case 12: h.x0 = 10; h.x1 = 12; h.y0 = 0; h.y1 = 1; break; // Gain 4
+ case 13: h.x0 = 11; h.x1 = 13; h.y0 = 1; h.y1 = 2; break; // Bandwidth 4
+ case 21: h.x0 = 10; h.x1 = 13; h.y0 = 5; h.y1 = 6; break; // enable 4
+
+ case 14: h.x0 = 13; h.x1 = 14; h.y0 = 2; h.y1 = 3; break; // Frequency H
+ case 15: h.x0 = 13; h.x1 = 14; h.y0 = 0; h.y1 = 1; break; // Gain H
+ case 22: h.x0 = 13; h.x1 = 14; h.y0 = 5; h.y1 = 6; break; // enable H
+
+
+ case 16: h.x0 = 14; h.x1 = 15; h.y0 = 4; h.y1 = 6; break; // Master Gain
+ default:
+ return false;
+ }
+ return true;
+}
+
uint32_t
LV2Plugin::nth_parameter(uint32_t n, bool& ok) const
{
LilvNode* render = get_value(lworld, unit, _world.units_render);
if (render) {
desc.print_fmt = lilv_node_as_string(render);
+ replace_all (desc.print_fmt, "%f", "%.2f");
lilv_node_free(render);
}
}
lilv_port_get_range(_impl->plugin, port, &def, &min, &max);
portunits = lilv_port_get_value(_impl->plugin, port, _world.units_unit);
+ LilvNode* steps = lilv_port_get(_impl->plugin, port, _world.ext_rangeSteps);
+
// TODO: Once we can rely on lilv 0.18.0 being present,
// load_parameter_descriptor() can be used for ports as well
desc.integer_step = lilv_port_has_property(_impl->plugin, port, _world.lv2_integer);
desc.update_steps();
+ if (steps) {
+ //override auto-calculated steps in update_steps()
+ float s = lilv_node_as_float (steps);
+ const float delta = desc.upper - desc.lower;
+
+ desc.step = desc.smallstep = (delta / s);
+ desc.largestep = std::min ((delta / 5.0f), 10.f * desc.smallstep);
+
+ if (desc.logarithmic) {
+ // TODO marry AutomationControl::internal_to_interface () with
+ // http://lv2plug.in/ns/ext/port-props/#rangeSteps
+ desc.smallstep = desc.smallstep / logf(s);
+ desc.step = desc.step / logf(s);
+ desc.largestep = desc.largestep / logf(s);
+ } else if (desc.integer_step) {
+ desc.smallstep = 1.0;
+ desc.step = std::max(1.f, rintf (desc.step));
+ desc.largestep = std::max(1.f, rintf (desc.largestep));
+ }
+ DEBUG_TRACE(DEBUG::LV2, string_compose("parameter %1 small: %2, step: %3 largestep: %4\n",
+ which, desc.smallstep, desc.step, desc.largestep));
+ }
+
+
lilv_node_free(def);
lilv_node_free(min);
lilv_node_free(max);
+ lilv_node_free(steps);
lilv_nodes_free(portunits);
return 0;
int
LV2Plugin::connect_and_run(BufferSet& bufs,
- ChanMapping in_map, ChanMapping out_map,
- pframes_t nframes, framecnt_t offset)
+ framepos_t start, framepos_t end, double speed,
+ ChanMapping in_map, ChanMapping out_map,
+ pframes_t nframes, framecnt_t offset)
{
DEBUG_TRACE(DEBUG::LV2, string_compose("%1 run %2 offset %3\n", name(), nframes, offset));
- Plugin::connect_and_run(bufs, in_map, out_map, nframes, offset);
+ Plugin::connect_and_run(bufs, start, end, speed, in_map, out_map, nframes, offset);
cycles_t then = get_cycles();
TempoMap& tmap = _session.tempo_map();
Metrics::const_iterator metric_i = tmap.metrics_end();
- TempoMetric tmetric = tmap.metric_at(_session.transport_frame(), &metric_i);
+ TempoMetric tmetric = tmap.metric_at(start, &metric_i);
if (_freewheel_control_port) {
*_freewheel_control_port = _session.engine().freewheeling() ? 1.f : 0.f;
}
#ifdef LV2_EXTENDED
- if (_can_write_automation && _session.transport_frame() != _next_cycle_start) {
+ if (_can_write_automation && start != _next_cycle_start) {
// add guard-points after locating
for (AutomationCtrlMap::iterator i = _ctrl_map.begin(); i != _ctrl_map.end(); ++i) {
i->second->guard = true;
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) {
+ if (start != _next_cycle_start ||
+ speed != _next_cycle_speed) {
// Transport has changed, write position at cycle start
- bbt = tmap.bbt_at_frame (_session.transport_frame());
+ bbt = tmap.bbt_at_frame (start);
write_position(&_impl->forge, _ev_buffers[port_index],
- tmetric, bbt, _session.transport_speed(),
- _session.transport_frame(), 0);
+ tmetric, bbt, speed, start, 0);
}
}
// Now merge MIDI and any transport events into the buffer
const uint32_t type = _uri_map.urids.midi_MidiEvent;
- const framepos_t tend = _session.transport_frame() + nframes;
+ const framepos_t tend = end;
++metric_i;
while (m != m_end || (metric_i != tmap.metrics_end() &&
(*metric_i)->frame() < tend)) {
tmetric.set_metric(metric);
bbt = tmap.bbt_at_pulse (metric->pulse());
write_position(&_impl->forge, _ev_buffers[port_index],
- tmetric, bbt, _session.transport_speed(),
+ tmetric, bbt, speed,
metric->frame(),
- metric->frame() - _session.transport_frame());
+ metric->frame() - start);
++metric_i;
}
}
if (c &&
(c->ac->automation_state() == Touch || c->ac->automation_state() == Write)
) {
- framepos_t when = std::max ((framepos_t) 0, _session.transport_frame() + frames - _current_latency);
- assert (_session.transport_frame() + frames - _current_latency >= 0);
+ framepos_t when = std::max ((framepos_t) 0, start + frames - _current_latency);
+ assert (start + frames - _current_latency >= 0);
if (c->guard) {
c->guard = false;
c->ac->list()->add (when, v, true, true);
AutomationCtrlPtr c = get_automation_control (p);
DEBUG_TRACE(DEBUG::LV2Automate, string_compose ("Start Touch p: %1\n", p));
if (c) {
- c->ac->start_touch (std::max ((framepos_t)0, _session.transport_frame() - _current_latency));
+ c->ac->start_touch (std::max ((framepos_t)0, start - _current_latency));
c->guard = true;
}
}
AutomationCtrlPtr c = get_automation_control (p);
DEBUG_TRACE(DEBUG::LV2Automate, string_compose ("End Touch p: %1\n", p));
if (c) {
- c->ac->stop_touch (true, std::max ((framepos_t)0, _session.transport_frame() - _current_latency));
+ c->ac->stop_touch (true, std::max ((framepos_t)0, start - _current_latency));
}
}
}
set_cycles((uint32_t)(now - then));
// Update expected transport information for next cycle so we can detect changes
- _next_cycle_speed = _session.transport_speed();
- _next_cycle_start = _session.transport_frame() + (nframes * _next_cycle_speed);
+ _next_cycle_speed = speed;
+ _next_cycle_start = end;
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;
return _port_flags[param] & PORT_INPUT;
}
+uint32_t
+LV2Plugin::designated_bypass_port ()
+{
+#ifdef LV2_EXTENDED
+ const LilvPort* port = NULL;
+ LilvNode* designation = lilv_new_uri (_world.world, LV2_PROCESSING_URI__enable);
+ port = lilv_plugin_get_port_by_designation (
+ _impl->plugin, _world.lv2_InputPort, designation);
+ lilv_node_free(designation);
+ if (port) {
+ return lilv_port_get_index (_impl->plugin, port);
+ }
+#endif
+ return UINT32_MAX;
+}
+
void
LV2Plugin::print_parameter(uint32_t param, char* buf, uint32_t len) const
{
ext_expensive = lilv_new_uri(world, LV2_PORT_PROPS__expensive);
ext_causesArtifacts= lilv_new_uri(world, LV2_PORT_PROPS__causesArtifacts);
ext_notAutomatic = lilv_new_uri(world, LV2_PORT_PROPS__notAutomatic);
+ ext_rangeSteps = lilv_new_uri(world, LV2_PORT_PROPS__rangeSteps);
lv2_AudioPort = lilv_new_uri(world, LILV_URI_AUDIO_PORT);
lv2_ControlPort = lilv_new_uri(world, LILV_URI_CONTROL_PORT);
lv2_InputPort = lilv_new_uri(world, LILV_URI_INPUT_PORT);
lilv_node_free(lv2_InputPort);
lilv_node_free(lv2_ControlPort);
lilv_node_free(lv2_AudioPort);
+ lilv_node_free(ext_rangeSteps);
lilv_node_free(ext_notAutomatic);
lilv_node_free(ext_causesArtifacts);
lilv_node_free(ext_expensive);