Replace half-baked param metadata with descriptor.
authorDavid Robillard <d@drobilla.net>
Mon, 1 Dec 2014 19:28:03 +0000 (14:28 -0500)
committerDavid Robillard <d@drobilla.net>
Tue, 2 Dec 2014 04:35:24 +0000 (23:35 -0500)
Among other things, this means that automation controls/lists have the actual
min/max/normal/toggled of parameters, and not those inferred from the Parameter
ID, which is not correct for things like plugin parameters.

Pushing things down to the Evoral::ParmeterDescriptor may be useful in the
future to have lists do smarter things based on parameter range, but currently
I have just pushed down the above-mentioned currently used attributes.

31 files changed:
gtk2_ardour/editor_ops.cc
gtk2_ardour/selection.cc
libs/ardour/MSVClibardour/ardour.vcproj
libs/ardour/amp.cc
libs/ardour/ardour/automation_list.h
libs/ardour/ardour/event_type_map.h
libs/ardour/ardour/parameter_descriptor.h
libs/ardour/audioregion.cc
libs/ardour/automatable.cc
libs/ardour/automation_control.cc
libs/ardour/automation_list.cc
libs/ardour/event_type_map.cc
libs/ardour/midi_automation_list_binder.cc
libs/ardour/midi_source.cc
libs/ardour/midi_track.cc
libs/ardour/parameter_descriptor.cc [new file with mode: 0644]
libs/ardour/plugin_insert.cc
libs/ardour/value_as_string.cc [new file with mode: 0644]
libs/ardour/wscript
libs/evoral/MSVCevoral/evoral.vcproj
libs/evoral/evoral/Control.hpp
libs/evoral/evoral/ControlList.hpp
libs/evoral/evoral/Parameter.hpp
libs/evoral/evoral/ParameterDescriptor.hpp [new file with mode: 0644]
libs/evoral/evoral/Sequence.hpp
libs/evoral/evoral/TypeMap.hpp
libs/evoral/src/Control.cpp
libs/evoral/src/ControlList.cpp
libs/evoral/src/ParameterDescriptor.cpp [new file with mode: 0644]
libs/evoral/src/Sequence.cpp
libs/evoral/test/SequenceTest.hpp

index e8ca0e1ee2f7754256fd5f579340cd402c62ed27..00703dfc944df5867ab615c163de99af6a270b02 100644 (file)
@@ -3941,7 +3941,7 @@ Editor::cut_copy_points (CutCopyOp op)
                */
                framepos_t start = std::numeric_limits<framepos_t>::max();
                for (Lists::iterator i = lists.begin(); i != lists.end(); ++i) {
-                       i->second.copy = i->first->create (i->first->parameter ());
+                       i->second.copy = i->first->create (i->first->parameter (), i->first->descriptor());
 
                        /* Calculate earliest start position of any point in selection. */
                        start = std::min(start, i->second.line->session_position(i->first->begin()));
index abb49b7daf0c895bf38885068b83bf8f61fc094b..7e2ee1338b00c35da9a18cebb9faf956fe0bfc76 100644 (file)
@@ -1265,7 +1265,7 @@ Selection::set_state (XMLNode const & node, int)
                        RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (id);
 
                        if (rtv) {
-                               boost::shared_ptr<AutomationTimeAxisView> atv = rtv->automation_child (EventTypeMap::instance().new_parameter (prop_parameter->value ()));
+                               boost::shared_ptr<AutomationTimeAxisView> atv = rtv->automation_child (EventTypeMap::instance().from_symbol (prop_parameter->value ()));
 
                                /* the automation could be for an entity that was never saved
                                   in the session file. Don't freak out if we can't find
index 59654107632a7c3d0d781f6c6871f33b6055d721..5d4b535343fc0db0f96d3ee84469c2d8d2fcc4c7 100644 (file)
                                RelativePath="..\panner_shell.cc"
                                >
                        </File>
+                       <File
+                               RelativePath="..\parameter_descriptor.cc"
+                               >
+                       </File>
                        <File
                                RelativePath="..\pcm_utils.cc"
                                >
index 2265c6de0312d177907a620bb25ff4fb5fae193e..0cf7049c47b8035ab290f131ed75581717d229b7 100644 (file)
@@ -46,7 +46,6 @@ Amp::Amp (Session& s)
        , _gain_automation_buffer(0)
 {
        Evoral::Parameter p (GainAutomation);
-       p.set_range (0, max_gain_coefficient, 1, false);
        boost::shared_ptr<AutomationList> gl (new AutomationList (p));
        _gain_control = boost::shared_ptr<GainControl> (new GainControl (X_("gaincontrol"), s, this, p, gl));
        _gain_control->set_flags (Controllable::GainLike);
index 28f9be3fd4521731d426417a0e024e1050ac5dc8..cfeaeafa86df7793a46765ef32257ccc32321ac6 100644 (file)
@@ -64,13 +64,15 @@ private:
 class LIBARDOUR_API AutomationList : public PBD::StatefulDestructible, public Evoral::ControlList
 {
   public:
-       AutomationList (Evoral::Parameter id);
+       AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc);
+       AutomationList (const Evoral::Parameter& id);
        AutomationList (const XMLNode&, Evoral::Parameter id);
        AutomationList (const AutomationList&);
        AutomationList (const AutomationList&, double start, double end);
        ~AutomationList();
 
-       virtual boost::shared_ptr<Evoral::ControlList> create(Evoral::Parameter id);
+       virtual boost::shared_ptr<ControlList> create(const Evoral::Parameter&           id,
+                                                     const Evoral::ParameterDescriptor& desc);
 
        AutomationList& operator= (const AutomationList&);
 
index f69d20b773e6b0ec0a2009b119ec3d7c9f186316..0d7e6237540824b96967fc47593fbeecd2c3409a 100644 (file)
 #ifndef __ardour_event_type_map_h__
 #define __ardour_event_type_map_h__
 
+#include <map>
 #include <string>
+
 #include "evoral/TypeMap.hpp"
 #include "evoral/ControlList.hpp"
+#include "evoral/ParameterDescriptor.hpp"
 
 #include "ardour/libardour_visibility.h"
 
@@ -43,19 +46,23 @@ public:
        uint32_t midi_event_type(uint8_t status) const;
        Evoral::ControlList::InterpolationStyle interpolation_of(const Evoral::Parameter& param);
 
-       bool                 is_integer(const Evoral::Parameter& param) const;
-       Evoral::Parameter    new_parameter(uint32_t type, uint8_t channel=0, uint32_t id=0) const;
-       Evoral::Parameter    new_parameter(const std::string& str) const;
-       std::string          to_symbol(const Evoral::Parameter& param) const;
+       Evoral::Parameter from_symbol(const std::string& str) const;
+       std::string       to_symbol(const Evoral::Parameter& param) const;
+
+       const Evoral::ParameterDescriptor& descriptor(const Evoral::Parameter& param) const;
 
-       bool                 is_midi_parameter(const Evoral::Parameter& param);
+       void set_descriptor(const Evoral::Parameter&           param,
+                           const Evoral::ParameterDescriptor& desc);
 
        URIMap& uri_map() { return _uri_map; }
 
 private:
+       typedef std::map<Evoral::Parameter, Evoral::ParameterDescriptor> Descriptors;
+
        EventTypeMap(URIMap& uri_map) : _uri_map(uri_map) {}
 
-       URIMap& _uri_map;
+       URIMap&     _uri_map;
+       Descriptors _descriptors;
 
        static EventTypeMap* event_type_map;
 };
index 41b1f031d13daa3a73efaaf1e8b6f387f986679f..d4bef550f549061904b77ab609da0779a80923b2 100644 (file)
@@ -21,7 +21,9 @@
 #define __ardour_parameter_descriptor_h__
 
 #include "ardour/variant.h"
+
 #include "evoral/Parameter.hpp"
+#include "evoral/ParameterDescriptor.hpp"
 
 namespace ARDOUR {
 
@@ -31,7 +33,7 @@ typedef std::map<const std::string, const float> ScalePoints;
  *
  * Essentially a union of LADSPA, VST and LV2 info.
  */
-struct ParameterDescriptor
+struct ParameterDescriptor : public Evoral::ParameterDescriptor
 {
        enum Unit {
                NONE,       ///< No unit
@@ -40,72 +42,12 @@ struct ParameterDescriptor
                HZ,         ///< Frequency in Hertz
        };
 
-       ParameterDescriptor(const Evoral::Parameter& parameter)
-               : key((uint32_t)-1)
-               , datatype(Variant::NOTHING)
-               , unit(NONE)
-               , normal(parameter.normal())
-               , lower(parameter.min())
-               , upper(parameter.max())
-               , step(0)
-               , smallstep(0)
-               , largestep(0)
-               , integer_step(parameter.type() >= MidiCCAutomation &&
-                              parameter.type() <= MidiChannelPressureAutomation)
-               , toggled(parameter.toggled())
-               , logarithmic(false)
-               , sr_dependent(false)
-               , min_unbound(0)
-               , max_unbound(0)
-               , enumeration(false)
-       {
-               if (parameter.type() == GainAutomation) {
-                       unit = DB;
-               }
-               update_steps();
-       }
-
-       ParameterDescriptor()
-               : key((uint32_t)-1)
-               , datatype(Variant::NOTHING)
-               , unit(NONE)
-               , normal(0)
-               , lower(0)
-               , upper(0)
-               , step(0)
-               , smallstep(0)
-               , largestep(0)
-               , integer_step(false)
-               , toggled(false)
-               , logarithmic(false)
-               , sr_dependent(false)
-               , min_unbound(0)
-               , max_unbound(0)
-               , enumeration(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 if (integer_step) {
-                       const float delta = upper - lower;
+       ParameterDescriptor(const Evoral::Parameter& parameter);
 
-                       smallstep = delta / 10000.0f;
-                       step      = delta / 1000.0f;
-                       largestep = delta / 40.0f;
+       ParameterDescriptor();
 
-                       smallstep = std::max(1.0, rint(smallstep));
-                       step      = std::max(1.0, rint(step));
-                       largestep = std::max(1.0, rint(largestep));
-               }
-               /* else: leave all others as default '0'
-                * in that case the UI (eg. AutomationController::create)
-                * uses internal_to_interface() to map the value
-                * to an appropriate interface range
-                */
-       }
+       /** Set step, smallstep, and largestep, based on current description. */
+       void update_steps();
 
        std::string                    label;
        std::string                    print_fmt;  ///< format string for pretty printing
@@ -113,14 +55,10 @@ struct ParameterDescriptor
        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)
        float                          step;
        float                          smallstep;
        float                          largestep;
        bool                           integer_step;
-       bool                           toggled;
        bool                           logarithmic;
        bool                           sr_dependent;
        bool                           min_unbound;
index 8c4eb6aa2a13d3f3eb2fb3a9bed2bedfcf7360d5..506596430f2d9fd01cd806a6936e3883c1efa18b 100644 (file)
 #include "ardour/session.h"
 #include "ardour/dB.h"
 #include "ardour/debug.h"
+#include "ardour/event_type_map.h"
 #include "ardour/playlist.h"
 #include "ardour/audiofilesource.h"
 #include "ardour/region_factory.h"
 #include "ardour/runtime_functions.h"
 #include "ardour/transient_detector.h"
+#include "ardour/parameter_descriptor.h"
 #include "ardour/progress.h"
 
 #include "i18n.h"
@@ -1011,9 +1013,10 @@ AudioRegion::set_fade_in (boost::shared_ptr<AutomationList> f)
 void
 AudioRegion::set_fade_in (FadeShape shape, framecnt_t len)
 {
-       boost::shared_ptr<Evoral::ControlList> c1 (new Evoral::ControlList (FadeInAutomation));
-       boost::shared_ptr<Evoral::ControlList> c2 (new Evoral::ControlList (FadeInAutomation));
-       boost::shared_ptr<Evoral::ControlList> c3 (new Evoral::ControlList (FadeInAutomation));
+       const ARDOUR::ParameterDescriptor desc(FadeInAutomation);
+       boost::shared_ptr<Evoral::ControlList> c1 (new Evoral::ControlList (FadeInAutomation, desc));
+       boost::shared_ptr<Evoral::ControlList> c2 (new Evoral::ControlList (FadeInAutomation, desc));
+       boost::shared_ptr<Evoral::ControlList> c3 (new Evoral::ControlList (FadeInAutomation, desc));
 
        _fade_in->freeze ();
        _fade_in->clear ();
@@ -1093,8 +1096,9 @@ AudioRegion::set_fade_out (boost::shared_ptr<AutomationList> f)
 void
 AudioRegion::set_fade_out (FadeShape shape, framecnt_t len)
 {
-       boost::shared_ptr<Evoral::ControlList> c1 (new Evoral::ControlList (FadeOutAutomation));
-       boost::shared_ptr<Evoral::ControlList> c2 (new Evoral::ControlList (FadeOutAutomation));
+       const ARDOUR::ParameterDescriptor desc(FadeOutAutomation);
+       boost::shared_ptr<Evoral::ControlList> c1 (new Evoral::ControlList (FadeOutAutomation, desc));
+       boost::shared_ptr<Evoral::ControlList> c2 (new Evoral::ControlList (FadeOutAutomation, desc));
 
        _fade_out->freeze ();
        _fade_out->clear ();
index 906ff4ed3ee2ad7b7a0a316a2293f3aaeab66d89..0538c84cc5917a6d74ef1c8291fce0af17aec7b5 100644 (file)
@@ -212,7 +212,7 @@ Automatable::set_automation_xml_state (const XMLNode& node, Evoral::Parameter le
                        const XMLProperty* id_prop = (*niter)->property("automation-id");
 
                        Evoral::Parameter param = (id_prop
-                                       ? EventTypeMap::instance().new_parameter(id_prop->value())
+                                       ? EventTypeMap::instance().from_symbol(id_prop->value())
                                        : legacy_param);
 
                        if (param.type() == NullAutomation) {
@@ -399,14 +399,15 @@ Automatable::transport_stopped (framepos_t now)
 boost::shared_ptr<Evoral::Control>
 Automatable::control_factory(const Evoral::Parameter& param)
 {
-       boost::shared_ptr<AutomationList> list(new AutomationList(param));
-       Evoral::Control* control = NULL;
-       ParameterDescriptor desc(param);
+       Evoral::Control*                  control   = NULL;
+       bool                              make_list = true;
+       ParameterDescriptor               desc(param);
+       boost::shared_ptr<AutomationList> list;
        if (param.type() >= MidiCCAutomation && param.type() <= MidiChannelPressureAutomation) {
                MidiTrack* mt = dynamic_cast<MidiTrack*>(this);
                if (mt) {
                        control = new MidiTrack::MidiControl(mt, param);
-                       list.reset();  // No list, this is region "automation"
+                       make_list = false;  // No list, this is region "automation"
                } else {
                        warning << "MidiCCAutomation for non-MidiTrack" << endl;
                }
@@ -424,7 +425,9 @@ Automatable::control_factory(const Evoral::Parameter& param)
                        desc = pi->plugin(0)->get_property_descriptor(param.id());
                        if (desc.datatype != Variant::NOTHING) {
                                if (!Variant::type_is_numeric(desc.datatype)) {
-                                       list.reset();  // Can't automate non-numeric data yet
+                                       make_list = false;  // Can't automate non-numeric data yet
+                               } else {
+                                       list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
                                }
                                control = new PluginInsert::PluginPropertyControl(pi, param, desc, list);
                        }
@@ -447,11 +450,14 @@ Automatable::control_factory(const Evoral::Parameter& param)
                }
        }
 
+       if (make_list && !list) {
+               list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
+       }
+
        if (!control) {
-               control = new AutomationControl(_a_session, param, desc);
+               control = new AutomationControl(_a_session, param, desc, list);
        }
 
-       control->set_list(list);
        return boost::shared_ptr<Evoral::Control>(control);
 }
 
index e21fda6874f551e192786ae73106601fb2413ca4..773fd3f40c8a2e2fcd8abb44d889adf5c99c2b2c 100644 (file)
@@ -35,7 +35,7 @@ AutomationControl::AutomationControl(ARDOUR::Session&                          s
                                      boost::shared_ptr<ARDOUR::AutomationList> list,
                                      const string&                             name)
        : Controllable (name.empty() ? EventTypeMap::instance().to_symbol(parameter) : name)
-       , Evoral::Control(parameter, list)
+       , Evoral::Control(parameter, desc, list)
        , _session(session)
        , _desc(desc)
 {
index e5a4493618b921a5ead23722e6b78b8b75c4382f..cf41c4183943c0dee50952c7cd1c0d89a5c900f3 100644 (file)
@@ -25,6 +25,7 @@
 #include <algorithm>
 #include "ardour/automation_list.h"
 #include "ardour/event_type_map.h"
+#include "ardour/parameter_descriptor.h"
 #include "evoral/Curve.hpp"
 #include "pbd/stacktrace.h"
 #include "pbd/enumwriter.h"
@@ -47,8 +48,21 @@ static void dumpit (const AutomationList& al, string prefix = "")
        cerr << "\n";
 }
 #endif
-AutomationList::AutomationList (Evoral::Parameter id)
-       : ControlList(id)
+AutomationList::AutomationList (const Evoral::Parameter& id, const Evoral::ParameterDescriptor& desc)
+       : ControlList(id, desc)
+{
+       _state = Off;
+       _style = Absolute;
+       g_atomic_int_set (&_touching, 0);
+
+       create_curve_if_necessary();
+
+       assert(_parameter.type() != NullAutomation);
+       AutomationListCreated(this);
+}
+
+AutomationList::AutomationList (const Evoral::Parameter& id)
+       : ControlList(id, ARDOUR::ParameterDescriptor(id))
 {
        _state = Off;
        _style = Absolute;
@@ -91,7 +105,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
  * in or below the AutomationList node.  It is used if @param id is non-null.
  */
 AutomationList::AutomationList (const XMLNode& node, Evoral::Parameter id)
-       : ControlList(id)
+       : ControlList(id, ARDOUR::ParameterDescriptor(id))
 {
        g_atomic_int_set (&_touching, 0);
        _state = Off;
@@ -114,9 +128,10 @@ AutomationList::~AutomationList()
 }
 
 boost::shared_ptr<Evoral::ControlList>
-AutomationList::create(Evoral::Parameter id)
+AutomationList::create(const Evoral::Parameter&           id,
+                       const Evoral::ParameterDescriptor& desc)
 {
-       return boost::shared_ptr<Evoral::ControlList>(new AutomationList(id));
+       return boost::shared_ptr<Evoral::ControlList>(new AutomationList(id, desc));
 }
 
 void
@@ -414,7 +429,7 @@ AutomationList::set_state (const XMLNode& node, int version)
        }
 
        if ((prop = node.property (X_("automation-id"))) != 0){
-               _parameter = EventTypeMap::instance().new_parameter(prop->value());
+               _parameter = EventTypeMap::instance().from_symbol(prop->value());
        } else {
                warning << "Legacy session: automation list has no automation-id property." << endmsg;
        }
index 6c1c8363eedd176770beefe9cc373dea296eef4b..14f609bd8a5615d0634bac6f1fc8885c5d69527d 100644 (file)
@@ -25,6 +25,7 @@
 #include "ardour/parameter_types.h"
 #include "ardour/uri_map.h"
 #include "evoral/Parameter.hpp"
+#include "evoral/ParameterDescriptor.hpp"
 #include "evoral/midi_events.h"
 #include "pbd/error.h"
 #include "pbd/compose.h"
@@ -40,25 +41,6 @@ EventTypeMap::instance()
 {
        if (!EventTypeMap::event_type_map) {
                EventTypeMap::event_type_map = new EventTypeMap(URIMap::instance());
-
-               // Initialize parameter metadata
-               EventTypeMap::event_type_map->new_parameter(NullAutomation);
-               EventTypeMap::event_type_map->new_parameter(GainAutomation);
-               EventTypeMap::event_type_map->new_parameter(PanAzimuthAutomation);
-               EventTypeMap::event_type_map->new_parameter(PanElevationAutomation);
-               EventTypeMap::event_type_map->new_parameter(PanWidthAutomation);
-               EventTypeMap::event_type_map->new_parameter(PluginAutomation);
-               EventTypeMap::event_type_map->new_parameter(PluginPropertyAutomation);
-               EventTypeMap::event_type_map->new_parameter(SoloAutomation);
-               EventTypeMap::event_type_map->new_parameter(MuteAutomation);
-               EventTypeMap::event_type_map->new_parameter(MidiCCAutomation);
-               EventTypeMap::event_type_map->new_parameter(MidiPgmChangeAutomation);
-               EventTypeMap::event_type_map->new_parameter(MidiPitchBenderAutomation);
-               EventTypeMap::event_type_map->new_parameter(MidiChannelPressureAutomation);
-               EventTypeMap::event_type_map->new_parameter(FadeInAutomation);
-               EventTypeMap::event_type_map->new_parameter(FadeOutAutomation);
-               EventTypeMap::event_type_map->new_parameter(EnvelopeAutomation);
-               EventTypeMap::event_type_map->new_parameter(MidiCCAutomation);
        }
        return *EventTypeMap::event_type_map;
 }
@@ -69,12 +51,6 @@ EventTypeMap::type_is_midi(uint32_t type) const
        return ARDOUR::parameter_is_midi((AutomationType)type);
 }
 
-bool
-EventTypeMap::is_midi_parameter(const Evoral::Parameter& param)
-{
-       return type_is_midi(param.type());
-}
-
 uint8_t
 EventTypeMap::parameter_midi_type(const Evoral::Parameter& param) const
 {
@@ -87,13 +63,6 @@ EventTypeMap::midi_event_type(uint8_t status) const
        return (uint32_t)ARDOUR::midi_parameter_type(status);
 }
 
-bool
-EventTypeMap::is_integer(const Evoral::Parameter& param) const
-{
-       return (   param.type() >= MidiCCAutomation
-                       && param.type() <= MidiChannelPressureAutomation);
-}
-
 Evoral::ControlList::InterpolationStyle
 EventTypeMap::interpolation_of(const Evoral::Parameter& param)
 {
@@ -147,75 +116,8 @@ EventTypeMap::interpolation_of(const Evoral::Parameter& param)
        return Evoral::ControlList::Linear; // Not reached, suppress warnings
 }
 
-
 Evoral::Parameter
-EventTypeMap::new_parameter(uint32_t type, uint8_t channel, uint32_t id) const
-{
-       Evoral::Parameter p(type, channel, id);
-
-       double min     = 0.0f;
-       double max     = 1.0f;
-       double normal  = 0.0f;
-       bool   toggled = false;
-
-       switch((AutomationType)type) {
-       case NullAutomation:
-       case GainAutomation:
-               max = 2.0f;
-               normal = 1.0f;
-               break;
-       case PanAzimuthAutomation:
-               normal = 0.5f; // there really is no normal but this works for stereo, sort of
-                break;
-       case PanWidthAutomation:
-                min = -1.0;
-                max = 1.0;
-               normal = 0.0f;
-                break;
-        case PanElevationAutomation:
-        case PanFrontBackAutomation:
-        case PanLFEAutomation:
-                break;
-       case RecEnableAutomation:
-               /* default 0.0 - 1.0 is fine */
-               toggled = true;
-               break;
-       case PluginAutomation:
-       case FadeInAutomation:
-       case FadeOutAutomation:
-       case EnvelopeAutomation:
-               max = 2.0f;
-               normal = 1.0f;
-               break;
-       case SoloAutomation:
-       case MuteAutomation:
-               max = 1.0f;
-               normal = 0.0f;
-               toggled = true;
-               break;
-       case MidiCCAutomation:
-       case MidiPgmChangeAutomation:
-       case MidiChannelPressureAutomation:
-               min = 0.0;
-               normal = 0.0;
-               max = 127.0;
-               break;
-       case MidiPitchBenderAutomation:
-               min = 0.0;
-               normal = 8192.0;
-               max = 16383.0;
-       case MidiSystemExclusiveAutomation:
-               return p;
-       case PluginPropertyAutomation:
-               return p;
-       }
-
-       p.set_range(type, min, max, normal, toggled);
-       return p;
-}
-
-Evoral::Parameter
-EventTypeMap::new_parameter(const string& str) const
+EventTypeMap::from_symbol(const string& str) const
 {
        AutomationType p_type    = NullAutomation;
        uint8_t        p_channel = 0;
@@ -285,7 +187,7 @@ EventTypeMap::new_parameter(const string& str) const
                PBD::warning << "Unknown Parameter '" << str << "'" << endmsg;
        }
        
-       return new_parameter(p_type, p_channel, p_id);
+       return Evoral::Parameter(p_type, p_channel, p_id);
 }
 
 /** Unique string representation, suitable as an XML property value.
@@ -341,5 +243,21 @@ EventTypeMap::to_symbol(const Evoral::Parameter& param) const
        }
 }
 
+const Evoral::ParameterDescriptor&
+EventTypeMap::descriptor(const Evoral::Parameter& param) const
+{
+       static const Evoral::ParameterDescriptor nil;
+
+       Descriptors::const_iterator d = _descriptors.find(param);
+       return (d != _descriptors.end()) ? d->second : nil;
+}
+
+void
+EventTypeMap::set_descriptor(const Evoral::Parameter&           param,
+                             const Evoral::ParameterDescriptor& desc)
+{
+       _descriptors.insert(std::make_pair(param, desc));
+}
+
 } // namespace ARDOUR
 
index fbb87c5cfa2a2265191ae3051529ea30bcf99d92..f7249d72b1e1b95303bc33e28ca3fd6269d76674 100644 (file)
@@ -45,7 +45,7 @@ MidiAutomationListBinder::MidiAutomationListBinder (XMLNode* node, Session::Sour
        assert (i != sources.end());
        _source = boost::dynamic_pointer_cast<MidiSource> (i->second);
 
-       _parameter = EventTypeMap::instance().new_parameter (parameter->value());
+       _parameter = EventTypeMap::instance().from_symbol (parameter->value());
 }
 
 AutomationList*
index 0f3df97f9b1216c8587988544013cbfb90ae393b..5bfa73518c040964170c77b736bc9e994a787a99 100644 (file)
@@ -123,7 +123,7 @@ MidiSource::set_state (const XMLNode& node, int /*version*/)
                                error << _("Missing parameter property on InterpolationStyle") << endmsg;
                                return -1;
                        }
-                       Evoral::Parameter p = EventTypeMap::instance().new_parameter (prop->value());
+                       Evoral::Parameter p = EventTypeMap::instance().from_symbol (prop->value());
 
                        if ((prop = (*i)->property (X_("style"))) == 0) {
                                error << _("Missing style property on InterpolationStyle") << endmsg;
@@ -138,7 +138,7 @@ MidiSource::set_state (const XMLNode& node, int /*version*/)
                                error << _("Missing parameter property on AutomationState") << endmsg;
                                return -1;
                        }
-                       Evoral::Parameter p = EventTypeMap::instance().new_parameter (prop->value());
+                       Evoral::Parameter p = EventTypeMap::instance().from_symbol (prop->value());
 
                        if ((prop = (*i)->property (X_("state"))) == 0) {
                                error << _("Missing state property on AutomationState") << endmsg;
index f7294d8e3b2ac3443c27c4aff92142a261bd7f34..b8fe7ada4c35d46084fa42dfa77eceb09d7f7837 100644 (file)
@@ -37,6 +37,7 @@
 #include "ardour/buffer_set.h"
 #include "ardour/debug.h"
 #include "ardour/delivery.h"
+#include "ardour/event_type_map.h"
 #include "ardour/meter.h"
 #include "ardour/midi_diskstream.h"
 #include "ardour/midi_playlist.h"
@@ -657,16 +658,17 @@ void
 MidiTrack::MidiControl::set_value(double val)
 {
        const Evoral::Parameter &parameter = _list ? _list->parameter() : Control::parameter();
+       const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter);
 
        bool valid = false;
        if (isinf_local(val)) {
                cerr << "MIDIControl value is infinity" << endl;
        } else if (isnan_local(val)) {
                cerr << "MIDIControl value is NaN" << endl;
-       } else if (val < parameter.min()) {
-               cerr << "MIDIControl value is < " << parameter.min() << endl;
-       } else if (val > parameter.max()) {
-               cerr << "MIDIControl value is > " << parameter.max() << endl;
+       } else if (val < desc.lower) {
+               cerr << "MIDIControl value is < " << desc.lower << endl;
+       } else if (val > desc.upper) {
+               cerr << "MIDIControl value is > " << desc.upper << endl;
        } else {
                valid = true;
        }
@@ -675,7 +677,7 @@ MidiTrack::MidiControl::set_value(double val)
                return;
        }
 
-       assert(val <= parameter.max());
+       assert(val <= desc.upper);
        if ( ! _list || ! automation_playback()) {
                size_t size = 3;
                uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 };
diff --git a/libs/ardour/parameter_descriptor.cc b/libs/ardour/parameter_descriptor.cc
new file mode 100644 (file)
index 0000000..88debb0
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+    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.
+*/
+
+#include "ardour/amp.h"
+#include "ardour/parameter_descriptor.h"
+#include "ardour/types.h"
+
+namespace ARDOUR {
+
+ParameterDescriptor::ParameterDescriptor(const Evoral::Parameter& parameter)
+       : Evoral::ParameterDescriptor()
+       , key((uint32_t)-1)
+       , datatype(Variant::NOTHING)
+       , unit(NONE)
+       , step(0)
+       , smallstep(0)
+       , largestep(0)
+       , integer_step(parameter.type() >= MidiCCAutomation &&
+                      parameter.type() <= MidiChannelPressureAutomation)
+       , logarithmic(false)
+       , sr_dependent(false)
+       , min_unbound(0)
+       , max_unbound(0)
+       , enumeration(false)
+{
+       if (parameter.type() == GainAutomation) {
+               unit = DB;
+       }
+
+       switch((AutomationType)parameter.type()) {
+       case GainAutomation:
+               upper  = Amp::max_gain_coefficient;
+               normal = 1.0f;
+               break;
+       case PanAzimuthAutomation:
+               normal = 0.5f; // there really is no _normal but this works for stereo, sort of
+               break;
+       case PanWidthAutomation:
+               lower  = -1.0;
+               upper  = 1.0;
+               normal = 0.0f;
+               break;
+       case RecEnableAutomation:
+               /* default 0.0 - 1.0 is fine */
+               toggled = true;
+               break;
+       case PluginAutomation:
+       case FadeInAutomation:
+       case FadeOutAutomation:
+       case EnvelopeAutomation:
+               upper  = 2.0f;
+               normal = 1.0f;
+               break;
+       case SoloAutomation:
+       case MuteAutomation:
+               upper  = 1.0f;
+               normal = 0.0f;
+               toggled = true;
+               break;
+       case MidiCCAutomation:
+       case MidiPgmChangeAutomation:
+       case MidiChannelPressureAutomation:
+               lower  = 0.0;
+               normal = 0.0;
+               upper  = 127.0;
+               break;
+       case MidiPitchBenderAutomation:
+               lower  = 0.0;
+               normal = 8192.0;
+               upper  = 16383.0;
+               break;
+       default:
+               break;
+       }
+
+       update_steps();
+}
+
+ParameterDescriptor::ParameterDescriptor()
+       : Evoral::ParameterDescriptor()
+       , key((uint32_t)-1)
+       , datatype(Variant::NOTHING)
+       , unit(NONE)
+       , step(0)
+       , smallstep(0)
+       , largestep(0)
+       , integer_step(false)
+       , logarithmic(false)
+       , sr_dependent(false)
+       , min_unbound(0)
+       , max_unbound(0)
+       , enumeration(false)
+{}
+
+void
+ParameterDescriptor::update_steps()
+{
+       if (unit == ParameterDescriptor::MIDI_NOTE) {
+               step      = smallstep = 1;  // semitone
+               largestep = 12;             // octave
+       } else if (integer_step) {
+               const float delta = upper - lower;
+
+               smallstep = delta / 10000.0f;
+               step      = delta / 1000.0f;
+               largestep = delta / 40.0f;
+
+               smallstep = std::max(1.0, rint(smallstep));
+               step      = std::max(1.0, rint(step));
+               largestep = std::max(1.0, rint(largestep));
+       }
+       /* else: leave all others as default '0'
+        * in that case the UI (eg. AutomationController::create)
+        * uses internal_to_interface() to map the value
+        * to an appropriate interface range
+        */
+}
+
+} // namespace ARDOUR
index 5dd35c881c58dac819452c00cf9490e91b2810bc..156f7b02a0df2a0114ad574fb99f26a68984ea63 100644 (file)
@@ -248,13 +248,8 @@ PluginInsert::create_automatable_parameters ()
                        ParameterDescriptor desc;
                        _plugins.front()->get_parameter_descriptor(i->id(), desc);
 
-                       /* the Parameter belonging to the actual plugin doesn't have its range set
-                          but we want the Controllable related to this Parameter to have those limits.
-                       */
-
-                       param.set_range (desc.lower, desc.upper, _plugins.front()->default_value(i->id()), desc.toggled);
                        can_automate (param);
-                       boost::shared_ptr<AutomationList> list(new AutomationList(param));
+                       boost::shared_ptr<AutomationList> list(new AutomationList(param, desc));
                        add_control (boost::shared_ptr<AutomationControl> (new PluginControl(this, param, desc, list)));
                } else if (i->type() == PluginPropertyAutomation) {
                        Evoral::Parameter param(*i);
@@ -262,7 +257,7 @@ PluginInsert::create_automatable_parameters ()
                        if (desc.datatype != Variant::NOTHING) {
                                boost::shared_ptr<AutomationList> list;
                                if (Variant::type_is_numeric(desc.datatype)) {
-                                       list = boost::shared_ptr<AutomationList>(new AutomationList(param));
+                                       list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
                                }
                                add_control (boost::shared_ptr<AutomationControl> (new PluginPropertyControl(this, param, desc, list)));
                        }
diff --git a/libs/ardour/value_as_string.cc b/libs/ardour/value_as_string.cc
new file mode 100644 (file)
index 0000000..3d79d24
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+    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.
+
+*/
+
+#include "ardour/value_as_string.h"
+
+namespace ARDOUR {
+
+std::string
+value_as_string(const Evoral::ParameterDescriptor& desc,
+                double                             v)
+{
+       char buf[32];
+
+       if (desc.scale_points) {
+               // Check if value is on a scale point
+               for (Evoral::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 == Evoral::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.print_fmt.empty()) {
+               snprintf(buf, sizeof(buf), desc.print_fmt.c_str(), v);
+       } else if (desc.integer_step) {
+               snprintf(buf, sizeof(buf), "%d", (int)v);
+       } else {
+               snprintf(buf, sizeof(buf), "%.3f", v);
+       }
+       if (desc.print_fmt.empty() && desc.unit == Evoral::ParameterDescriptor::DB) {
+               // TODO: Move proper dB printing from AutomationLine here
+               return std::string(buf) + " dB";
+       }
+       return buf;
+}
+
+std::string
+value_as_string(const Evoral::ParameterDescriptor& desc,
+                const Evoral::Variant&             val)
+{
+       // Only numeric support, for now
+       return value_as_string(desc, val.to_double());
+}
+
+}  // namespace ARDOUR
index 0abeb865a48757cda19aeb39b592d8643ed35c13..beca18f0e552a11b33361824535b8bf54cf5b2c9 100644 (file)
@@ -141,6 +141,7 @@ libardour_sources = [
         'panner.cc',
         'panner_manager.cc',
         'panner_shell.cc',
+        'parameter_descriptor.cc',
         'pcm_utils.cc',
         'playlist.cc',
         'playlist_factory.cc',
index e58711405e1f8823951a40bb9733cf1b6453277e..60abf730d44514addf5a16af39a0df4fe9823f9e 100644 (file)
                                RelativePath="..\evoral\Parameter.hpp"
                                >
                        </File>
+                       <File
+                               RelativePath="..\evoral\ParameterDescriptor.hpp"
+                               >
+                       </File>
                        <File
                                RelativePath="..\evoral\PatchChange.hpp"
                                >
index ea1e9b89e534b723b39b683980f8952d371456b8..d91c89bb744b63438e180796dd6f83b9bc02d201 100644 (file)
 
 #include "evoral/visibility.h"
 #include "evoral/Parameter.hpp"
+#include "evoral/ParameterDescriptor.hpp"
 
 namespace Evoral {
 
 class ControlList;
+class ParameterDescriptor;
 class Transport;
+class TypeMap;
 
 /** Base class representing some kind of (automatable) control; a fader's gain,
  *  for example, or a compressor plugin's threshold.
@@ -38,11 +41,13 @@ class Transport;
  *  The class knows the Evoral::Parameter that it is controlling, and has
  *  a list of values for automation.
  */
-
 class LIBEVORAL_API Control
 {
 public:
-       Control(const Parameter& parameter, boost::shared_ptr<ControlList>);
+       Control(const Parameter&               parameter,
+               const ParameterDescriptor&     desc,
+               boost::shared_ptr<ControlList> list);
+
        virtual ~Control() {}
 
         virtual void   set_double (double val, double frame=0, bool to_list=false);
index d6704c8e43adad153d74aa91a7f98d995f1704d0..ed7fc75732963645219cfeee37c0869ed757c9d4 100644 (file)
 #include "evoral/types.hpp"
 #include "evoral/Range.hpp"
 #include "evoral/Parameter.hpp"
+#include "evoral/ParameterDescriptor.hpp"
 
 namespace Evoral {
 
 class Curve;
+class TypeMap;
 
 /** A single event (time-stamped value) for a control
  */
@@ -82,12 +84,12 @@ public:
        typedef EventList::const_iterator const_iterator;
        typedef EventList::const_reverse_iterator const_reverse_iterator;
 
-       ControlList (const Parameter& id);
+       ControlList (const Parameter& id, const ParameterDescriptor& desc);
        ControlList (const ControlList&);
        ControlList (const ControlList&, double start, double end);
        virtual ~ControlList();
 
-       virtual boost::shared_ptr<ControlList> create(Parameter id);
+       virtual boost::shared_ptr<ControlList> create(const Parameter& id, const ParameterDescriptor& desc);
 
         void dump (std::ostream&);
 
@@ -102,6 +104,9 @@ public:
        const Parameter& parameter() const                 { return _parameter; }
        void             set_parameter(const Parameter& p) { _parameter = p; }
 
+       const ParameterDescriptor& descriptor() const                           { return _desc; }
+       void                       set_descriptor(const ParameterDescriptor& d) { _desc = d; }
+
        EventList::size_type size() const { return _events.size(); }
         double length() const {                
                Glib::Threads::Mutex::Lock lm (_lock);
@@ -218,7 +223,7 @@ public:
        };
 
        const EventList& events() const { return _events; }
-       double default_value() const { return _parameter.normal(); }
+       double default_value() const { return _default_value; }
 
        // FIXME: const violations for Curve
        Glib::Threads::Mutex& lock()         const { return _lock; }
@@ -288,10 +293,12 @@ protected:
        mutable LookupCache   _lookup_cache;
        mutable SearchCache   _search_cache;
 
+       mutable Glib::Threads::Mutex _lock;
+
        Parameter             _parameter;
+       ParameterDescriptor   _desc;
        InterpolationStyle    _interpolation;
        EventList             _events;
-       mutable Glib::Threads::Mutex   _lock;
        int8_t                _frozen;
        bool                  _changed_when_thawed;
        double                _min_yval;
index 2164475cf9635f34e73567b08031f4fb94a5815a..c870fa8e99f6e49ae295cd99b3a8a62c2f421173 100644 (file)
@@ -28,7 +28,6 @@
 
 namespace Evoral {
 
-
 /** ID of a [play|record|automate]able parameter.
  *
  * A parameter is defined by (type, id, channel).  Type is an integer which
@@ -41,12 +40,10 @@ namespace Evoral {
 class LIBEVORAL_API Parameter
 {
 public:
-       Parameter(uint32_t type, uint8_t channel=0, uint32_t id=0)
+       inline Parameter(uint32_t type, uint8_t channel=0, uint32_t id=0)
                : _type(type), _id(id), _channel(channel)
        {}
 
-       virtual ~Parameter() {}
-
        inline uint32_t type()    const { return _type; }
        inline uint8_t  channel() const { return _channel; }
        inline uint32_t id()      const { return _id; }
@@ -78,52 +75,12 @@ public:
 
        inline operator bool() const { return (_type != 0); }
 
-       /** Not used in indentity/comparison */
-       struct Metadata {
-               Metadata(double low=0.0, double high=1.0, double mid=0.0, bool tog=false)
-                       : min(low), max(high), normal(mid), toggled(tog)
-               {}
-               double min;
-               double max;
-               double normal;
-               bool   toggled;
-       };
-
-       inline static void set_range(uint32_t type, double min, double max, double normal, bool toggled) {
-               _type_metadata[type] = Metadata(min, max, normal, toggled);
-       }
-
-       inline void set_range(double min, double max, double normal, bool toggled) {
-               _metadata = boost::shared_ptr<Metadata>(new Metadata(min, max, normal, toggled));
-       }
-
-       inline Metadata& metadata() const {
-               if (_metadata)
-                       return *_metadata.get();
-               else
-                       return _type_metadata[_type];
-       }
-
-       inline double min()     const { return metadata().min; }
-       inline double max()     const { return metadata().max; }
-       inline double normal()  const { return metadata().normal; }
-       inline double toggled() const { return metadata().toggled; }
-
-protected:
-       // Default copy constructor is ok
-
-       // ID (used in comparison)
+private:
        uint32_t _type;
        uint32_t _id;
        uint8_t  _channel;
-
-       boost::shared_ptr<Metadata> _metadata;
-
-       typedef std::map<uint32_t, Metadata> TypeMetadata;
-       static TypeMetadata _type_metadata;
 };
 
-
 } // namespace Evoral
 
 #endif // EVORAL_PARAMETER_HPP
diff --git a/libs/evoral/evoral/ParameterDescriptor.hpp b/libs/evoral/evoral/ParameterDescriptor.hpp
new file mode 100644 (file)
index 0000000..0323db1
--- /dev/null
@@ -0,0 +1,42 @@
+/* This file is part of Evoral.
+ * Copyright (C) 2000-2014 Paul Davis
+ * Author: David Robillard
+ *
+ * Evoral 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.
+ *
+ * Evoral 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 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef EVORAL_PARAMETER_DESCRIPTOR_HPP
+#define EVORAL_PARAMETER_DESCRIPTOR_HPP
+
+namespace Evoral {
+
+/** Description of the value range of a parameter or control. */
+struct ParameterDescriptor
+{
+       ParameterDescriptor()
+               : normal(0.0)
+               , lower(0.0)
+               , upper(0.0)
+               , toggled(false)
+       {}
+
+       float normal;   ///< Default value
+       float lower;    ///< Minimum value (in Hz, for frequencies)
+       float upper;    ///< Maximum value (in Hz, for frequencies)
+       bool  toggled;  ///< True iff parameter is boolean
+};
+
+} // namespace Evoral
+
+#endif // EVORAL_PARAMETER_DESCRIPTOR_HPP
index e40c4da925f7c3ce23db3081f496de17d4c9738d..9aded0d9f010d7594730efce011d5a5394e9ec85 100644 (file)
 #include "evoral/visibility.h"
 #include "evoral/types.hpp"
 #include "evoral/Note.hpp"
-#include "evoral/Parameter.hpp"
 #include "evoral/ControlSet.hpp"
 #include "evoral/ControlList.hpp"
 #include "evoral/PatchChange.hpp"
 
 namespace Evoral {
 
+class Parameter;
 class TypeMap;
 template<typename Time> class EventSink;
 template<typename Time> class Note;
@@ -109,6 +109,8 @@ public:
 
        void append(const Event<Time>& ev, Evoral::event_id_t evid);
 
+       const TypeMap& type_map() const { return _type_map; }
+
        inline size_t n_notes() const { return _notes.size(); }
        inline bool   empty()   const { return _notes.empty() && _sysexes.empty() && _patch_changes.empty() && ControlSet::controls_empty(); }
 
index 987706e541e3f7a32da7c90e43d061deff0fcd47..154cdff613c1f6779859d092154f9955d489eb77 100644 (file)
@@ -28,6 +28,7 @@
 namespace Evoral {
 
 class Parameter;
+class ParameterDescriptor;
 
 /** The applications passes one of these which provide the implementation
  * with required information about event types in an opaque, type neutral way
@@ -50,11 +51,8 @@ public:
         */
        virtual uint32_t midi_event_type(uint8_t status) const = 0;
 
-       /** Return true iff parameter should be locked to integer boundaries */
-       virtual bool is_integer(const Evoral::Parameter& param) const = 0;
-
-       /** Create a parameter with the given type ID */
-       virtual Parameter new_parameter(uint32_t type, uint8_t channel, uint32_t id) const = 0;
+       /** Return the description of a parameter. */
+       virtual const ParameterDescriptor& descriptor(const Parameter& param) const = 0;
 
        virtual std::string to_symbol(const Parameter& param) const = 0;
 };
index 480d027ccc85812ae6a750d9bc861e6c2a2f5322..b7537c57edca08cbb942a75c01810c57561af5b3 100644 (file)
 
 #include "evoral/Control.hpp"
 #include "evoral/ControlList.hpp"
+#include "evoral/ParameterDescriptor.hpp"
+#include "evoral/TypeMap.hpp"
 
 namespace Evoral {
 
-Parameter::TypeMetadata Parameter::_type_metadata;
-
-Control::Control(const Parameter& parameter, boost::shared_ptr<ControlList> list)
+Control::Control(const Parameter&               parameter,
+                 const ParameterDescriptor&     desc,
+                 boost::shared_ptr<ControlList> list)
        : _parameter(parameter)
-       , _user_value(list ? list->default_value() : parameter.normal())
+       , _user_value(list ? list->default_value() : desc.normal)
 {
        set_list (list);
 }
index 0876cdef28cc412bac98cb238b6edeadb5dc91eb..a4b98934c207777d54feb172f5f3a4f1d52e1ce9 100644 (file)
 #endif
 
 #include <cassert>
-#include <utility>
+#include <cmath>
 #include <iostream>
+#include <utility>
+
 #include "evoral/ControlList.hpp"
 #include "evoral/Curve.hpp"
+#include "evoral/ParameterDescriptor.hpp"
+#include "evoral/TypeMap.hpp"
 
 #include "pbd/compose.h"
 #include "pbd/debug.h"
@@ -46,16 +50,17 @@ inline bool event_time_less_than (ControlEvent* a, ControlEvent* b)
        return a->when < b->when;
 }
 
-ControlList::ControlList (const Parameter& id)
+ControlList::ControlList (const Parameter& id, const ParameterDescriptor& desc)
        : _parameter(id)
-       , _interpolation(id.toggled() ? Discrete : Linear)
+       , _desc(desc)
        , _curve(0)
 {
+       _interpolation = desc.toggled ? Discrete : Linear;
        _frozen = 0;
        _changed_when_thawed = false;
-       _min_yval = id.min();
-       _max_yval = id.max();
-       _default_value = id.normal();
+       _min_yval = desc.lower;
+       _max_yval = desc.upper;
+       _default_value = desc.normal;
        _lookup_cache.left = -1;
        _lookup_cache.range.first = _events.end();
        _lookup_cache.range.second = _events.end();
@@ -71,6 +76,7 @@ ControlList::ControlList (const Parameter& id)
 
 ControlList::ControlList (const ControlList& other)
        : _parameter(other._parameter)
+       , _desc(other._desc)
        , _interpolation(other._interpolation)
        , _curve(0)
 {
@@ -96,6 +102,7 @@ ControlList::ControlList (const ControlList& other)
 
 ControlList::ControlList (const ControlList& other, double start, double end)
        : _parameter(other._parameter)
+       , _desc(other._desc)
        , _interpolation(other._interpolation)
        , _curve(0)
 {
@@ -136,9 +143,9 @@ ControlList::~ControlList()
 }
 
 boost::shared_ptr<ControlList>
-ControlList::create(Parameter id)
+ControlList::create(const Parameter& id, const ParameterDescriptor& desc)
 {
-       return boost::shared_ptr<ControlList>(new ControlList(id));
+       return boost::shared_ptr<ControlList>(new ControlList(id, desc));
 }
 
 bool
@@ -1503,7 +1510,7 @@ ControlList::rt_safe_earliest_event_linear_unlocked (double start, double& x, do
 boost::shared_ptr<ControlList>
 ControlList::cut_copy_clear (double start, double end, int op)
 {
-       boost::shared_ptr<ControlList> nal = create (_parameter);
+       boost::shared_ptr<ControlList> nal = create (_parameter, _desc);
        iterator s, e;
        ControlEvent cp (start, 0.0);
 
diff --git a/libs/evoral/src/ParameterDescriptor.cpp b/libs/evoral/src/ParameterDescriptor.cpp
new file mode 100644 (file)
index 0000000..ffac8d2
--- /dev/null
@@ -0,0 +1,67 @@
+/* This file is part of Evoral.
+ * Copyright (C) 2000-2014 Paul Davis
+ * Author: David Robillard
+ *
+ * Evoral 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.
+ *
+ * Evoral 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 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "evoral/ParameterDescriptor.hpp"
+
+namespace Evoral {
+
+ParameterDescriptor::ParameterDescriptor()
+       : key((uint32_t)-1)
+       , datatype(Variant::NOTHING)
+       , unit(NONE)
+       , normal(0)
+       , lower(0)
+       , upper(0)
+       , step(0)
+       , smallstep(0)
+       , largestep(0)
+       , integer_step(false)
+       , toggled(false)
+       , logarithmic(false)
+       , sr_dependent(false)
+       , min_unbound(0)
+       , max_unbound(0)
+       , enumeration(false)
+{}
+
+/* Set step, smallstep, and largestep, based on current description */
+void
+ParameterDescriptor::update_steps()
+{
+       if (unit == ParameterDescriptor::MIDI_NOTE) {
+               step      = smallstep = 1;  // semitone
+               largestep = 12;             // octave
+       } else if (integer_step) {
+               const float delta = upper - lower;
+
+               smallstep = delta / 10000.0f;
+               step      = delta / 1000.0f;
+               largestep = delta / 40.0f;
+
+               smallstep = std::max(1.0, rint(smallstep));
+               step      = std::max(1.0, rint(step));
+               largestep = std::max(1.0, rint(largestep));
+       }
+       /* else: leave all others as default '0'
+        * in that case the UI (eg. AutomationController::create)
+        * uses internal_to_interface() to map the value
+        * to an appropriate interface range
+        */
+}
+
+}  // namespace Evoral
index fca4879322054f73dd9aae8ef47be003ede65306..dd891a0ac2c15e027c38ccd349e6f5b01e7ce4ce 100644 (file)
@@ -35,6 +35,7 @@
 #include "evoral/ControlList.hpp"
 #include "evoral/ControlSet.hpp"
 #include "evoral/EventSink.hpp"
+#include "evoral/ParameterDescriptor.hpp"
 #include "evoral/Sequence.hpp"
 #include "evoral/TypeMap.hpp"
 #include "evoral/midi_util.h"
@@ -140,9 +141,10 @@ Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t
 
                assert(x >= 0);
 
-               if (y < i->first.min() || y > i->first.max()) {
+               const ParameterDescriptor& desc = seq.type_map().descriptor(i->first);
+               if (y < desc.lower || y > desc.upper) {
                        cerr << "ERROR: Controller value " << y
-                            << " out of range [" << i->first.min() << "," << i->first.max()
+                            << " out of range [" << desc.lower << "," << desc.upper
                             << "], event ignored" << endl;
                        continue;
                }
index 7b79d8fc12b6839de1e48819af5a4009b261cc5a..a21e8c34086c173efa92979081961d3a7448b3e0 100644 (file)
@@ -39,14 +39,6 @@ public:
                };
        }
 
-       bool is_integer (const Parameter& /*param*/) const { return true; }
-
-       Parameter new_parameter(uint32_t type, uint8_t channel, uint32_t id) const {
-               Parameter p(type, channel, id);
-               p.set_range(type, 0.0f, 1.0f, 0.0f);
-               return p;
-       }
-
        std::string to_symbol(const Parameter& /*param*/) const { return "control"; }
 };