summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/automation_line.cc24
-rw-r--r--gtk2_ardour/automation_line.h4
-rw-r--r--gtk2_ardour/automation_time_axis.cc3
-rw-r--r--gtk2_ardour/generic_pluginui.cc49
-rw-r--r--gtk2_ardour/midi_automation_line.cc2
-rw-r--r--gtk2_ardour/region_gain_line.cc2
-rw-r--r--libs/ardour/ardour/parameter_descriptor.h45
-rw-r--r--libs/ardour/ardour/value_as_string.h81
-rw-r--r--libs/ardour/automatable.cc17
-rw-r--r--libs/ardour/lv2_plugin.cc45
10 files changed, 175 insertions, 97 deletions
diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc
index c1549ecab3..2e9f988bfa 100644
--- a/gtk2_ardour/automation_line.cc
+++ b/gtk2_ardour/automation_line.cc
@@ -58,6 +58,7 @@
#include "ardour/event_type_map.h"
#include "ardour/session.h"
+#include "ardour/value_as_string.h"
#include "i18n.h"
@@ -73,6 +74,7 @@ AutomationLine::AutomationLine (const string& name,
TimeAxisView& tv,
ArdourCanvas::Item& parent,
boost::shared_ptr<AutomationList> al,
+ const ParameterDescriptor& desc,
Evoral::TimeConverter<double, framepos_t>* converter)
: trackview (tv)
, _name (name)
@@ -81,6 +83,7 @@ AutomationLine::AutomationLine (const string& name,
, _parent_group (parent)
, _offset (0)
, _maximum_time (max_framepos)
+ , _desc (desc)
{
if (converter) {
_our_time_converter = false;
@@ -112,7 +115,8 @@ AutomationLine::AutomationLine (const string& name,
trackview.session()->register_with_memento_command_factory(alist->id(), this);
if (alist->parameter().type() == GainAutomation ||
- alist->parameter().type() == EnvelopeAutomation) {
+ alist->parameter().type() == EnvelopeAutomation ||
+ desc.unit == ParameterDescriptor::DB) {
set_uses_gain_mapping (true);
}
@@ -356,24 +360,20 @@ AutomationLine::get_verbose_cursor_relative_string (double original, double frac
string
AutomationLine::fraction_to_string (double fraction) const
{
- char buf[32];
-
if (_uses_gain_mapping) {
+ char buf[32];
if (fraction == 0.0) {
snprintf (buf, sizeof (buf), "-inf");
} else {
snprintf (buf, sizeof (buf), "%.1f", accurate_coefficient_to_dB (slider_position_to_gain_with_max (fraction, Config->get_max_gain())));
}
+ return buf;
} else {
view_to_model_coord_y (fraction);
- if (EventTypeMap::instance().is_integer (alist->parameter())) {
- snprintf (buf, sizeof (buf), "%d", (int)fraction);
- } else {
- snprintf (buf, sizeof (buf), "%.2f", fraction);
- }
+ return ARDOUR::value_as_string (_desc, fraction);
}
- return buf;
+ return ""; /*NOTREACHED*/
}
/**
@@ -406,11 +406,7 @@ AutomationLine::fraction_to_relative_string (double original, double fraction) c
} else {
view_to_model_coord_y (original);
view_to_model_coord_y (fraction);
- if (EventTypeMap::instance().is_integer (alist->parameter())) {
- snprintf (buf, sizeof (buf), "%d", (int)fraction - (int)original);
- } else {
- snprintf (buf, sizeof (buf), "%.2f", fraction - original);
- }
+ return ARDOUR::value_as_string (_desc, fraction - original);
}
return buf;
diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h
index 02c67d0dcf..a18f93d9ae 100644
--- a/gtk2_ardour/automation_line.h
+++ b/gtk2_ardour/automation_line.h
@@ -34,6 +34,7 @@
#include "pbd/memento_command.h"
#include "ardour/automation_list.h"
+#include "ardour/parameter_descriptor.h"
#include "ardour/types.h"
#include "canvas/types.h"
@@ -64,6 +65,7 @@ public:
TimeAxisView& tv,
ArdourCanvas::Item& parent,
boost::shared_ptr<ARDOUR::AutomationList> al,
+ const ARDOUR::ParameterDescriptor& desc,
Evoral::TimeConverter<double, ARDOUR::framepos_t>* converter = 0);
virtual ~AutomationLine ();
@@ -234,6 +236,8 @@ private:
/** maximum time that a point on this line can be at, relative to the position of its region or start of its track */
ARDOUR::framecnt_t _maximum_time;
+ const ARDOUR::ParameterDescriptor _desc;
+
friend class AudioRegionGainLine;
};
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index a49bcf0086..3d2773b879 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -250,7 +250,8 @@ AutomationTimeAxisView::AutomationTimeAxisView (
ARDOUR::EventTypeMap::instance().to_symbol(_parameter),
*this,
*_canvas_display,
- _control->alist()
+ _control->alist(),
+ _control->desc()
)
);
diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc
index fb35882b34..a4de4fd75e 100644
--- a/gtk2_ardour/generic_pluginui.cc
+++ b/gtk2_ardour/generic_pluginui.cc
@@ -41,6 +41,7 @@
#include "ardour/plugin.h"
#include "ardour/plugin_insert.h"
#include "ardour/session.h"
+#include "ardour/value_as_string.h"
#include "ardour_ui.h"
#include "prompter.h"
@@ -504,51 +505,23 @@ GenericPluginUI::automation_state_changed (ControlUI* cui)
}
}
-
bool
GenericPluginUI::integer_printer (char buf[32], Adjustment &adj, ControlUI* cui)
{
- float const v = adj.get_value ();
-
- if (cui->scale_points) {
- ScalePoints::const_iterator i = cui->scale_points->begin ();
- while (i != cui->scale_points->end() && i->second != v) {
- ++i;
- }
-
- if (i != cui->scale_points->end ()) {
- snprintf (buf, 32, "%s", i->first.c_str());
- return true;
- }
- }
-
- snprintf (buf, 32, "%.0f", v);
+ float const v = cui->control->interface_to_internal(adj.get_value ());
+ const std::string& str = ARDOUR::value_as_string(cui->control->desc(), Variant(v));
+ const size_t len = str.copy(buf, 31);
+ buf[len] = '\0';
return true;
}
bool
GenericPluginUI::midinote_printer (char buf[32], Adjustment &adj, ControlUI* cui)
{
- float const v = adj.get_value ();
-
- if (cui->scale_points) {
- ScalePoints::const_iterator i = cui->scale_points->begin ();
- while (i != cui->scale_points->end() && i->second != v) {
- ++i;
- }
-
- if (i != cui->scale_points->end ()) {
- snprintf (buf, 32, "%s", i->first.c_str());
- return true;
- }
- }
- if (v >= 0 && v <= 127) {
- int mn = rint(v);
- const char notename[12][3] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
- snprintf (buf, 32, "%s %d", notename[mn%12], (mn/12)-2);
- } else {
- snprintf (buf, 32, "%.0f", v);
- }
+ float const v = cui->control->interface_to_internal(adj.get_value ());
+ const std::string& str = ARDOUR::value_as_string(cui->control->desc(), Variant(v));
+ const size_t len = str.copy(buf, 31);
+ buf[len] = '\0';
return true;
}
@@ -687,9 +660,9 @@ GenericPluginUI::build_control_ui (const ParameterDescriptor& desc,
Adjustment* adj = control_ui->controller->adjustment();
if (desc.integer_step) {
- control_ui->clickbox = new ClickBox (adj, "PluginUIClickBox");
+ control_ui->clickbox = new ClickBox (adj, "PluginUIClickBox", desc.enumeration);
Gtkmm2ext::set_size_request_to_display_given_text (*control_ui->clickbox, "g9999999", 2, 2);
- if (desc.midinote) {
+ if (desc.unit == ParameterDescriptor::MIDI_NOTE) {
control_ui->clickbox->set_printer (sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::midinote_printer), control_ui));
} else {
control_ui->clickbox->set_printer (sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::integer_printer), control_ui));
diff --git a/gtk2_ardour/midi_automation_line.cc b/gtk2_ardour/midi_automation_line.cc
index e5f30493d7..30bb37c5b0 100644
--- a/gtk2_ardour/midi_automation_line.cc
+++ b/gtk2_ardour/midi_automation_line.cc
@@ -34,7 +34,7 @@ MidiAutomationLine::MidiAutomationLine (
boost::shared_ptr<ARDOUR::MidiRegion> region,
Evoral::Parameter parameter,
Evoral::TimeConverter<double, ARDOUR::framepos_t>* converter)
- : AutomationLine (name, tav, parent, list, converter)
+ : AutomationLine (name, tav, parent, list, parameter, converter)
, _region (region)
, _parameter (parameter)
{
diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc
index 43cd0e5140..b010efc04c 100644
--- a/gtk2_ardour/region_gain_line.cc
+++ b/gtk2_ardour/region_gain_line.cc
@@ -38,7 +38,7 @@ using namespace ARDOUR;
using namespace PBD;
AudioRegionGainLine::AudioRegionGainLine (const string & name, AudioRegionView& r, ArdourCanvas::Container& parent, boost::shared_ptr<AutomationList> l)
- : AutomationLine (name, r.get_time_axis_view(), parent, l)
+ : AutomationLine (name, r.get_time_axis_view(), parent, l, l->parameter())
, rv (r)
{
// If this isn't true something is horribly wrong, and we'll get catastrophic gain values
diff --git a/libs/ardour/ardour/parameter_descriptor.h b/libs/ardour/ardour/parameter_descriptor.h
index 8916f081a3..1576230b8f 100644
--- a/libs/ardour/ardour/parameter_descriptor.h
+++ b/libs/ardour/ardour/parameter_descriptor.h
@@ -33,24 +33,34 @@ typedef std::map<const std::string, const float> ScalePoints;
*/
struct ParameterDescriptor
{
+ enum Unit {
+ NONE, ///< No unit
+ DB, ///< Decibels
+ MIDI_NOTE, ///< MIDI note number
+ };
+
ParameterDescriptor(const Evoral::Parameter& parameter)
: key((uint32_t)-1)
, datatype(Variant::VOID)
, normal(parameter.normal())
, lower(parameter.min())
, upper(parameter.max())
- , step(0)
- , smallstep((upper - lower) / 100.0)
- , largestep((upper - lower) / 10.0)
- , integer_step(false)
+ , step((upper - lower) / 100.0f)
+ , smallstep((upper - lower) / 1000.0f)
+ , largestep((upper - lower) / 10.0f)
+ , integer_step(parameter.type() >= MidiCCAutomation &&
+ parameter.type() <= MidiChannelPressureAutomation)
, toggled(parameter.toggled())
, logarithmic(false)
, sr_dependent(false)
, min_unbound(0)
, max_unbound(0)
, enumeration(false)
- , midinote(false)
- {}
+ {
+ if (parameter.type() == GainAutomation) {
+ unit = DB;
+ }
+ }
ParameterDescriptor()
: key((uint32_t)-1)
@@ -68,13 +78,33 @@ struct ParameterDescriptor
, min_unbound(0)
, max_unbound(0)
, enumeration(false)
- , midinote(false)
{}
+ /// Set step, smallstep, and largestep, based on current description
+ void update_steps() {
+ if (unit == ParameterDescriptor::MIDI_NOTE) {
+ step = smallstep = 1; // semitone
+ largestep = 12; // octave
+ } else {
+ const float delta = upper - lower;
+
+ step = delta / 1000.0f;
+ smallstep = delta / 10000.0f;
+ largestep = delta / 10.0f;
+
+ if (integer_step) {
+ step = rint(step);
+ largestep = rint(largestep);
+ // leave smallstep alone for fine tuning
+ }
+ }
+ }
+
std::string label;
boost::shared_ptr<ScalePoints> scale_points;
uint32_t key; ///< for properties
Variant::Type datatype; ///< for properties
+ Unit unit;
float normal;
float lower; ///< for frequencies, this is in Hz (not a fraction of the sample rate)
float upper; ///< for frequencies, this is in Hz (not a fraction of the sample rate)
@@ -88,7 +118,6 @@ struct ParameterDescriptor
bool min_unbound;
bool max_unbound;
bool enumeration;
- bool midinote; ///< only used if integer_step is also true
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/value_as_string.h b/libs/ardour/ardour/value_as_string.h
new file mode 100644
index 0000000000..6c17ace5d3
--- /dev/null
+++ b/libs/ardour/ardour/value_as_string.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2014 Paul Davis
+ Author: David Robillard
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_value_as_string_h__
+#define __ardour_value_as_string_h__
+
+#include <stddef.h>
+
+#include "ardour/parameter_descriptor.h"
+
+namespace ARDOUR {
+
+inline std::string
+value_as_string(const ARDOUR::ParameterDescriptor& desc,
+ double v)
+{
+ char buf[32];
+
+ if (desc.scale_points) {
+ // Check if value is on a scale point
+ for (ARDOUR::ScalePoints::const_iterator i = desc.scale_points->begin();
+ i != desc.scale_points->end();
+ ++i) {
+ if (i->second == v) {
+ return i->first; // Found it, return scale point label
+ }
+ }
+ }
+
+ // Value is not a scale point, print it normally
+ if (desc.unit == ARDOUR::ParameterDescriptor::MIDI_NOTE) {
+ if (v >= 0 && v <= 127) {
+ const int num = rint(v);
+ static const char names[12][3] = {
+ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
+ };
+ snprintf(buf, sizeof(buf), "%s %d", names[num % 12], (num / 12) - 2);
+ } else {
+ // Odd, invalid range, just print the number
+ snprintf(buf, sizeof(buf), "%.0f", v);
+ }
+ } else if (desc.integer_step) {
+ snprintf(buf, sizeof(buf), "%d", (int)v);
+ } else {
+ snprintf(buf, sizeof(buf), "%.2f", v);
+ }
+ if (desc.unit == ARDOUR::ParameterDescriptor::DB) {
+ // TODO: Move proper dB printing from AutomationLine here
+ return std::string(buf) + " dB";
+ }
+ return buf;
+}
+
+inline std::string
+value_as_string(const ARDOUR::ParameterDescriptor& desc,
+ const ARDOUR::Variant& val)
+{
+ // Only numeric support, for now
+ return value_as_string(desc, val.to_double());
+}
+
+} // namespace ARDOUR
+
+#endif /* __ardour_value_as_string_h__ */
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index 466899ce48..b4d957c8b6 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -35,6 +35,7 @@
#include "ardour/plugin_insert.h"
#include "ardour/session.h"
#include "ardour/uri_map.h"
+#include "ardour/value_as_string.h"
#include "i18n.h"
@@ -474,19 +475,5 @@ Automatable::clear_controls ()
string
Automatable::value_as_string (boost::shared_ptr<AutomationControl> ac) const
{
- std::stringstream s;
-
- /* this is a the default fallback for this virtual method. Derived Automatables
- are free to override this to display the values of their parameters/controls
- in different ways.
- */
-
- // Hack to display CC as integer value, rather than double
- if (ac->parameter().type() == MidiCCAutomation) {
- s << lrint (ac->get_value());
- } else {
- s << std::fixed << std::setprecision(3) << ac->get_value();
- }
-
- return s.str ();
+ return ARDOUR::value_as_string(ac->desc(), ac->get_value());
}
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index cf33c22424..dca91fd646 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -66,6 +66,7 @@
#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/units/units.h"
#include "lv2/lv2plug.in/ns/ext/patch/patch.h"
#ifdef HAVE_LV2_1_2_0
#include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h"
@@ -138,6 +139,7 @@ public:
LilvNode* ui_GtkUI;
LilvNode* ui_external;
LilvNode* ui_externalkx;
+ LilvNode* units_db;
LilvNode* units_unit;
LilvNode* units_midiNote;
LilvNode* patch_writable;
@@ -1312,10 +1314,10 @@ LV2Plugin::get_property_descriptor(uint32_t id) const
}
static void
-set_parameter_descriptor(LV2World& world,
- ParameterDescriptor& desc,
- Variant::Type datatype,
- const LilvNode* subject)
+load_parameter_descriptor(LV2World& world,
+ ParameterDescriptor& desc,
+ Variant::Type datatype,
+ const LilvNode* subject)
{
LilvWorld* lworld = _world.world;
LilvNode* label = lilv_world_get(lworld, subject, _world.rdfs_label, NULL);
@@ -1337,6 +1339,12 @@ set_parameter_descriptor(LV2World& world,
desc.datatype = datatype;
desc.toggled |= datatype == Variant::BOOL;
desc.integer_step |= datatype == Variant::INT || datatype == Variant::LONG;
+ if (lilv_world_ask(lworld, subject, _world.units_unit, _world.units_midiNote)) {
+ desc.unit = ParameterDescriptor::MIDI_NOTE;
+ } else if (lilv_world_ask(lworld, subject, _world.units_unit, _world.units_db)) {
+ desc.unit = ParameterDescriptor::DB;
+ }
+ desc.update_steps();
}
void
@@ -1368,7 +1376,7 @@ LV2Plugin::load_supported_properties(PropertyDescriptors& descs)
ParameterDescriptor desc;
desc.key = _uri_map.uri_to_id(lilv_node_as_uri(prop));
desc.datatype = datatype;
- set_parameter_descriptor(_world, desc, datatype, prop);
+ load_parameter_descriptor(_world, desc, datatype, prop);
descs.insert(std::make_pair(desc.key, desc));
lilv_node_free(range);
@@ -1560,6 +1568,8 @@ LV2Plugin::get_parameter_descriptor(uint32_t which, ParameterDescriptor& desc) c
lilv_port_get_range(_impl->plugin, port, &def, &min, &max);
portunits = lilv_port_get_value(_impl->plugin, port, _world.units_unit);
+ // 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.toggled = lilv_port_has_property(_impl->plugin, port, _world.lv2_toggled);
desc.logarithmic = lilv_port_has_property(_impl->plugin, port, _world.ext_logarithmic);
@@ -1567,7 +1577,11 @@ LV2Plugin::get_parameter_descriptor(uint32_t which, ParameterDescriptor& desc) c
desc.label = lilv_node_as_string(lilv_port_get_name(_impl->plugin, port));
desc.lower = min ? lilv_node_as_float(min) : 0.0f;
desc.upper = max ? lilv_node_as_float(max) : 1.0f;
- desc.midinote = lilv_nodes_contains(portunits, _world.units_midiNote);
+ if (lilv_nodes_contains(portunits, _world.units_midiNote)) {
+ desc.unit = ParameterDescriptor::MIDI_NOTE;
+ } else if (lilv_nodes_contains(portunits, _world.units_db)) {
+ desc.unit = ParameterDescriptor::DB;
+ }
if (desc.sr_dependent) {
desc.lower *= _session.frame_rate ();
@@ -1577,20 +1591,11 @@ LV2Plugin::get_parameter_descriptor(uint32_t which, ParameterDescriptor& desc) c
desc.min_unbound = false; // TODO: LV2 extension required
desc.max_unbound = false; // TODO: LV2 extension required
- if (desc.integer_step) {
- desc.step = 1.0;
- desc.smallstep = 0.1;
- desc.largestep = 10.0;
- } else {
- const float delta = desc.upper - desc.lower;
- desc.step = delta / 1000.0f;
- desc.smallstep = delta / 10000.0f;
- desc.largestep = delta / 10.0f;
- }
-
desc.enumeration = lilv_port_has_property(_impl->plugin, port, _world.lv2_enumeration);
desc.scale_points = get_scale_points(which);
+ desc.update_steps();
+
lilv_node_free(def);
lilv_node_free(min);
lilv_node_free(max);
@@ -2274,8 +2279,9 @@ LV2World::LV2World()
ui_GtkUI = lilv_new_uri(world, LV2_UI__GtkUI);
ui_external = lilv_new_uri(world, "http://lv2plug.in/ns/extensions/ui#external");
ui_externalkx = lilv_new_uri(world, "http://kxstudio.sf.net/ns/lv2ext/external-ui#Widget");
- units_unit = lilv_new_uri(world, "http://lv2plug.in/ns/extensions/units#unit");
- units_midiNote = lilv_new_uri(world, "http://lv2plug.in/ns/extensions/units#midiNote");
+ units_unit = lilv_new_uri(world, LV2_UNITS__unit);
+ units_midiNote = lilv_new_uri(world, LV2_UNITS__midiNote);
+ 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);
}
@@ -2285,6 +2291,7 @@ LV2World::~LV2World()
lilv_node_free(patch_Message);
lilv_node_free(patch_writable);
lilv_node_free(units_midiNote);
+ lilv_node_free(units_db);
lilv_node_free(units_unit);
lilv_node_free(ui_externalkx);
lilv_node_free(ui_external);