Fix parameter range stuff and automation time axis height (somewhat...).
authorDavid Robillard <d@drobilla.net>
Fri, 19 Sep 2008 06:30:49 +0000 (06:30 +0000)
committerDavid Robillard <d@drobilla.net>
Fri, 19 Sep 2008 06:30:49 +0000 (06:30 +0000)
Create a new AutomationLine when an AutomationRegionView without a line is clicked.

git-svn-id: svn://localhost/ardour2/branches/3.0@3757 d708f5d6-7413-0410-9779-e7cbd77b26cf

26 files changed:
gtk2_ardour/ardour_ui2.cc
gtk2_ardour/automation_line.h
gtk2_ardour/automation_region_view.cc
gtk2_ardour/automation_region_view.h
gtk2_ardour/automation_streamview.cc
gtk2_ardour/crossfade_edit.cc
gtk2_ardour/curvetest.cc
gtk2_ardour/editor_route_list.cc
gtk2_ardour/region_view.h
libs/ardour/ardour/midi_region.h
libs/ardour/ardour/parameter.h
libs/ardour/ardour/plugin_insert.h
libs/ardour/audioengine.cc
libs/ardour/midi_track.cc
libs/ardour/parameter.cc
libs/ardour/plugin_insert.cc
libs/evoral/evoral/Control.hpp
libs/evoral/evoral/ControlList.hpp
libs/evoral/evoral/ControlSet.hpp
libs/evoral/evoral/MIDIParameters.hpp
libs/evoral/evoral/Parameter.hpp
libs/evoral/evoral/Sequence.hpp
libs/evoral/src/Control.cpp
libs/evoral/src/ControlList.cpp
libs/evoral/src/ControlSet.cpp
libs/evoral/src/Sequence.cpp

index 568bfb54edfb6816dcf9a1fe187f5145a56b6afa..e40b7ea30f7f0f91934554d9d054b08cc8c732a1 100644 (file)
@@ -115,7 +115,7 @@ ARDOUR_UI::display_message (const char *prefix, gint prefix_len, RefPtr<TextBuff
        } else if (strcmp (prefix, _("[INFO]: ")) == 0) {
                text = "<span color=\"green\" weight=\"bold\">";
        } else {
-               text = "<span color=\"blue\" weight=\"bold\">???";
+               text = "<span color=\"white\" weight=\"bold\">???";
        }
 
        text += prefix;
index bc9c75e8f78c40fb24735ce948c2cebf56fb23b4..5a1b63740b41e5790641ccb6394620dfcf3642aa 100644 (file)
@@ -143,8 +143,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulThingWithGoin
 
        ArdourCanvas::Group&  _parent_group;
        ArdourCanvas::Group*   group;
-       ArdourCanvas::Line*   line; /* line */
-       ArdourCanvas::Points  line_points; /* coordinates for canvas line */
+       ArdourCanvas::Line*    line; /* line */
+       ArdourCanvas::Points   line_points; /* coordinates for canvas line */
        vector<ControlPoint*>  control_points; /* visible control points */
 
        struct ALPoint {
index 00cb8be5c426b8df531c4209f588c5a649b9f264..7b43f2f0af772884c8806cf87c0e4b8409c2c91d 100644 (file)
 AutomationRegionView::AutomationRegionView(ArdourCanvas::Group*                      parent,
                                            AutomationTimeAxisView&                   time_axis,
                                            boost::shared_ptr<ARDOUR::Region>         region,
+                                           const ARDOUR::Parameter&                  param,
                                            boost::shared_ptr<ARDOUR::AutomationList> list,
                                            double                                    spu,
                                            Gdk::Color&                               basic_color)
        : RegionView(parent, time_axis, region, spu, basic_color)
+       , _parameter(param)
 { 
        if (list) {
-               _line = boost::shared_ptr<AutomationLine>(new AutomationLine(
-                                       list->parameter().symbol(), time_axis, *group, list));
-               _line->set_colors();
-               _line->show();
-               _line->show_all_control_points();
+               assert(list->parameter() == param);
+               create_line(list);
        }
        
        group->signal_event().connect (mem_fun (this, &AutomationRegionView::canvas_event), false);
@@ -62,6 +61,18 @@ AutomationRegionView::init (Gdk::Color& basic_color, bool wfd)
        _enable_display = true;
 }
 
+void
+AutomationRegionView::create_line (boost::shared_ptr<ARDOUR::AutomationList> list)
+{
+       _line = boost::shared_ptr<AutomationLine>(new AutomationLine(
+                               list->parameter().symbol(), trackview, *get_canvas_group(), list));
+       _line->set_colors();
+       _line->show();
+       _line->show_all_control_points();
+       _line->set_y_position_and_height (trackview.y_position,
+               (uint32_t)rint(trackview.current_height() - NAME_HIGHLIGHT_SIZE));
+}
+
 bool
 AutomationRegionView::canvas_event(GdkEvent* ev)
 {
@@ -79,9 +90,13 @@ void
 AutomationRegionView::add_automation_event (GdkEvent* event, nframes_t when, double y)
 {
        if (!_line) {
-               cerr << "ERROR: AutomationRegionView::add_automation_event called without line" << endl;
-               return;
+               boost::shared_ptr<Evoral::Control> c = _region->control(_parameter, true);
+               boost::shared_ptr<ARDOUR::AutomationControl> ac
+                               = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(c);
+               assert(ac);
+               create_line(ac->alist());
        }
+       assert(_line);
 
        double x = 0;
        AutomationTimeAxisView* const view = automation_view();
@@ -109,14 +124,24 @@ AutomationRegionView::add_automation_event (GdkEvent* event, nframes_t when, dou
        view->session().set_dirty ();
 }
 
-
 void
 AutomationRegionView::set_y_position_and_height (double y, double h)
 {
+       cout << "ARV SET Y POSITION AND HEIGHT: " << y << ", " << h << endl;
        RegionView::set_y_position_and_height(y, h - 1);
 
        if (_line)
-               _line->set_y_position_and_height ((uint32_t)y, (uint32_t) rint (h - NAME_HIGHLIGHT_SIZE));
+               _line->set_y_position_and_height (y, h - NAME_HIGHLIGHT_SIZE);
+}
+
+void
+AutomationRegionView::set_height (double h)
+{
+       cout << "ARV SET HEIGHT: " << h << endl;
+       RegionView::set_height(h);
+       if (_line)
+               _line->set_y_position_and_height (trackview.y_position - h,
+                               (uint32_t)rint(h - NAME_HIGHLIGHT_SIZE));
 }
 
 bool
index e69845461c3c319f782482183f72a49137bf6372..90fa9f3e44282984c789313ae862dd7260a3cad7 100644 (file)
@@ -31,6 +31,7 @@
 
 namespace ARDOUR {
        class AutomationList;
+       class Parameter;
 };
 
 class TimeAxisView;
@@ -41,6 +42,7 @@ public:
        AutomationRegionView(ArdourCanvas::Group*,
                             AutomationTimeAxisView&,
                             boost::shared_ptr<ARDOUR::Region>,
+                            const ARDOUR::Parameter& parameter,
                             boost::shared_ptr<ARDOUR::AutomationList>,
                             double initial_samples_per_unit,
                             Gdk::Color& basic_color);
@@ -57,9 +59,11 @@ public:
        // We are a ghost.  Meta ghosts?  Crazy talk.
        virtual GhostRegion* add_ghost(TimeAxisView&) { return NULL; }
        
+       void set_height (double);
        void reset_width_dependent_items(double pixel_width);
 
 protected:
+       void create_line(boost::shared_ptr<ARDOUR::AutomationList> list);
        bool set_position(nframes_t pos, void* src, double* ignored);
        void set_y_position_and_height(double y, double h);
        void region_resized(ARDOUR::Change what_changed);
@@ -69,6 +73,7 @@ protected:
        void exited();
 
 private:
+       ARDOUR::Parameter                 _parameter;
        boost::shared_ptr<AutomationLine> _line;
 };
 
index 68da972ba01bafc58f7d41d568699cee89c5437f..206dc3753b61028ec24c5a7a2fd565ace864a1e3 100644 (file)
@@ -88,8 +88,10 @@ AutomationStreamView::add_region_view_internal (boost::shared_ptr<Region> region
                                region->control(_controller->controllable()->parameter()));
 
        boost::shared_ptr<AutomationList> list;
-       if (control)
+       if (control) {
                list = boost::dynamic_pointer_cast<AutomationList>(control->list());
+               assert(!control->list() || list);
+       }
 
        AutomationRegionView *region_view;
        std::list<RegionView *>::iterator i;
@@ -107,7 +109,8 @@ AutomationStreamView::add_region_view_internal (boost::shared_ptr<Region> region
                }
        }
        
-       region_view = new AutomationRegionView (canvas_group, _automation_view, region, list,
+       region_view = new AutomationRegionView (canvas_group, _automation_view, region,
+                       _controller->controllable()->parameter(), list,
                        _samples_per_unit, region_color);
                
        region_view->init (region_color, false);
index 3e85bd22db443c08dbc77e21bf73e8ef41e78493..6e4cbb345755ef337a019ecde64871fafecce27a 100644 (file)
@@ -65,7 +65,8 @@ CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0;
 
 CrossfadeEditor::Half::Half ()
        : line (0), 
-         normative_curve (Parameter(GainAutomation, 0.0, 1.0, 1.0)), // FIXME: GainAutomation?
+         //normative_curve (Parameter(GainAutomation, 0.0, 1.0, 1.0)), // FIXME: GainAutomation?
+         normative_curve (Parameter(GainAutomation)),
          gain_curve (Parameter(GainAutomation))
 {
 }
index 88c7b8e1167de2269ad1054a8102ba44086873df..9235fb9ba9e2414fa64a0fffa1af8d87775453ca 100644 (file)
@@ -34,7 +34,8 @@ curvetest (string filename)
 {
        ifstream in (filename.c_str());
        stringstream line;
-       Parameter param(GainAutomation, -1.0, +1.0, 0.0);
+       //Parameter param(GainAutomation, -1.0, +1.0, 0.0);
+       Parameter param(GainAutomation);
        AutomationList al (param);
        double minx = DBL_MAX;
        double maxx = DBL_MIN;
index f2b8456fd9b3a58a7f292bb830ef2d719a39c11f..1dd9a44e801bcd4c53d715b5dd90fc80ae1aa46c 100644 (file)
@@ -414,7 +414,7 @@ Editor::hide_all_tracks (bool with_select)
 void
 Editor::build_route_list_menu ()
 {
-        using namespace Menu_Helpers;
+       using namespace Menu_Helpers;
        using namespace Gtk;
 
        route_list_menu = new Menu;
@@ -434,7 +434,7 @@ Editor::build_route_list_menu ()
 void
 Editor::set_all_tracks_visibility (bool yn)
 {
-        TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = route_display_model->children();
        TreeModel::Children::iterator i;
 
        no_route_list_redisplay = true;
@@ -458,7 +458,7 @@ Editor::set_all_tracks_visibility (bool yn)
 void
 Editor::set_all_audio_visibility (int tracks, bool yn) 
 {
-        TreeModel::Children rows = route_display_model->children();
+       TreeModel::Children rows = route_display_model->children();
        TreeModel::Children::iterator i;
 
        no_route_list_redisplay = true;
index 579b6e55940678bb5a1409981dfdeb92dd4c5050..a001e241f1d3655fb29cbedea6715f0f272578c6 100644 (file)
@@ -58,7 +58,6 @@ class RegionView : public TimeAxisViewItem
        
        bool is_valid() const    { return valid; }
 
-
        void set_valid (bool yn) { valid = yn; }
        
        virtual void set_height (double);
index 66257372a92fb805a1cd3886728e84601e7d8912..e0caddd954958e1c0155f458c5ca5cce5dac5ce8 100644 (file)
@@ -80,10 +80,10 @@ class MidiRegion : public Region
        Controls&       controls()       { return midi_source()->model()->controls(); }
        const Controls& controls() const { return midi_source()->model()->controls(); }
        
-       boost::shared_ptr<Evoral::Control> control(Evoral::Parameter id, bool create_if_missing=false)
-                       { return midi_source()->model()->control(id, create_if_missing); }
+       boost::shared_ptr<Evoral::Control> control(const Evoral::Parameter& id, bool create=false)
+                       { return midi_source()->model()->control(id, create); }
 
-       boost::shared_ptr<const Evoral::Control> control(Evoral::Parameter id) const
+       boost::shared_ptr<const Evoral::Control> control(const Evoral::Parameter& id) const
                        { return midi_source()->model()->control(id); }
        
        int exportme (ARDOUR::Session&, ARDOUR::ExportSpecification&);
index dbcccd811f3d7189b2367649fc2deb2f502e5239..9ffeb98995ec3bc3f729abd5c04b734ef409aa4e 100644 (file)
@@ -47,50 +47,58 @@ public:
        Parameter(AutomationType type = NullAutomation, uint32_t id=0, uint8_t channel=0)
                : Evoral::Parameter((uint32_t)type, id, channel)
        {
-               init(type);
+               init_metadata(type);
        }
        
+#if 0
        Parameter(AutomationType type, double min, double max, double normal)
                : Evoral::Parameter((uint32_t)type, 0, 0, min, max, normal)
        {}
        
+       Parameter(const Parameter& copy)
+               : Evoral::Parameter(copy)
+       {
+               _min = copy._min;
+               _max = copy._max;
+               _normal = copy._max;
+       }
+#endif
+
        Parameter(const Evoral::Parameter& copy)
                : Evoral::Parameter(copy)
        {
-               init((AutomationType)_type);
        }
        
-       void init(AutomationType type) {
-               _normal = 0.0f;
+       static void init_metadata(AutomationType type) {
+               double min    = 0.0f;
+               double max    = 1.0f;
+               double normal = 0.0f;
                switch(type) {
                case NullAutomation:
                case GainAutomation:
-                       _min = 0.0f;
-                       _max = 2.0f;
-                       _normal = 1.0f;
+                       max = 2.0f;
+                       normal = 1.0f;
                        break;
                case PanAutomation:
-                       _min = 0.0f;
-                       _max = 1.0f;
-                       _normal = 0.5f;
+                       normal = 0.5f;
+                       break;
                case PluginAutomation:
                case SoloAutomation:
                case MuteAutomation:
                case FadeInAutomation:
                case FadeOutAutomation:
                case EnvelopeAutomation:
-                       _min = 0.0f;
-                       _max = 2.0f;
-                       _normal = 1.0f;
+                       max = 2.0f;
+                       normal = 1.0f;
+                       break;
                case MidiCCAutomation:
-                       Evoral::MIDI::ContinuousController::set_range(*this); break;
                case MidiPgmChangeAutomation:
-                       Evoral::MIDI::ProgramChange::set_range(*this); break;
-               case MidiPitchBenderAutomation:
-                       Evoral::MIDI::PitchBender::set_range(*this); break;
                case MidiChannelAftertouchAutomation:
-                       Evoral::MIDI::ChannelAftertouch::set_range(*this); break;
+                       Evoral::MIDI::controller_range(min, max, normal); break;
+               case MidiPitchBenderAutomation:
+                       Evoral::MIDI::bender_range(min, max, normal); break;
                }
+               set_range(type, min, max, normal);
        }
        
        Parameter(const std::string& str);
index f80f26098d6c01ab5ba2f5260661aa246c8c12d2..859c707c79f43740ad8df075b2f8e95ef1789c94 100644 (file)
@@ -77,7 +77,7 @@ class PluginInsert : public Processor
        void  set_parameter (Parameter param, float val);
        float get_parameter (Parameter param);
 
-       float default_parameter_value (Evoral::Parameter param);
+       float default_parameter_value (const Evoral::Parameter& param);
        
        struct PluginControl : public AutomationControl 
        {
index 6a76e98c3c5efdda5c23d72bccb3bba82105552d..71481e695f0900272e11d2bb096af3cf43e5b408 100644 (file)
@@ -85,6 +85,21 @@ AudioEngine::AudioEngine (string client_name)
        }
 
        Port::set_engine (this);
+       
+       Parameter::init_metadata(NullAutomation);
+       Parameter::init_metadata(GainAutomation);
+       Parameter::init_metadata(PanAutomation);
+       Parameter::init_metadata(PluginAutomation);
+       Parameter::init_metadata(SoloAutomation);
+       Parameter::init_metadata(MuteAutomation);
+       Parameter::init_metadata(MidiCCAutomation);
+       Parameter::init_metadata(MidiPgmChangeAutomation);
+       Parameter::init_metadata(MidiPitchBenderAutomation);
+       Parameter::init_metadata(MidiChannelAftertouchAutomation);
+       Parameter::init_metadata(FadeInAutomation);
+       Parameter::init_metadata(FadeOutAutomation);
+       Parameter::init_metadata(EnvelopeAutomation);
+       Parameter::init_metadata(MidiCCAutomation);
 }
 
 AudioEngine::~AudioEngine ()
index c1203d7ba953456e49153ee016153c52e56c109f..ffe8b203039924bfc7d43a34e7e7776bb1696842 100644 (file)
@@ -729,7 +729,23 @@ MidiTrack::write_immediate_event(size_t size, const uint8_t* buf)
 void
 MidiTrack::MidiControl::set_value(float val)
 {
-       assert(val >= _list->parameter().min());
+       bool valid = false;
+       if (isinf(val)) {
+               cerr << "MIDIControl value is infinity" << endl;
+       } else if (isnan(val)) {
+               cerr << "MIDIControl value is NaN" << endl;
+       } else if (val < _list->parameter().min()) {
+               cerr << "MIDIControl value is < " << _list->parameter().min() << endl;
+       } else if (val > _list->parameter().max()) {
+               cerr << "MIDIControl value is > " << _list->parameter().max() << endl;
+       } else {
+               valid = true;
+       }
+       
+       if (!valid) {
+               return;
+       }
+
        assert(val <= _list->parameter().max());
        size_t size = 3;
 
index ea70ea7927e94e640f170ab3084349df2ea4b6a7..87b5d329a23827fe4d92a86f13ca6403c9fccd9d 100644 (file)
@@ -79,7 +79,7 @@ Parameter::Parameter(const std::string& str)
                PBD::warning << "Unknown Parameter '" << str << "'" << endmsg;
        }
 
-       init((AutomationType)_type); // set min/max/normal
+       init_metadata((AutomationType)_type); // set min/max/normal
 }
 
 
@@ -114,7 +114,7 @@ Parameter::symbol() const
        } else if (_type == MidiChannelAftertouchAutomation) {
                return string_compose("midi-channel-aftertouch-%1", int(_channel));
        } else {
-               PBD::warning << "Uninitialized Parameter to_string() called." << endmsg;
+               PBD::warning << "Uninitialized Parameter symbol() called." << endmsg;
                return "";
        }
 }
index 4f92295e5541e30fd6fca48a6c093e209fbc30cf..b82ba28290c985de0e686a3f1837492bf3071465 100644 (file)
@@ -430,7 +430,7 @@ PluginInsert::automation_run (BufferSet& bufs, nframes_t nframes, nframes_t offs
 }      
 
 float
-PluginInsert::default_parameter_value (Evoral::Parameter param)
+PluginInsert::default_parameter_value (const Evoral::Parameter& param)
 {
        if (param.type() != PluginAutomation)
                return 1.0;
index ed957522a14f4e3037b95cb5d3bf8e7775be62b7..15d50fcdcab430a3e3f03516fc6bdff38a1d2948 100644 (file)
@@ -46,7 +46,7 @@ public:
        boost::shared_ptr<ControlList>       list()       { return _list; }
        boost::shared_ptr<const ControlList> list() const { return _list; }
 
-       Parameter parameter() const;
+       const Parameter& parameter() const;
 
 protected:
        boost::shared_ptr<ControlList> _list;
index c035b6ddcf4906cd49e1ea135c15767c65d68904..45519955c5ecef60443b48fcc79b2727728a4e1b 100644 (file)
@@ -83,7 +83,7 @@ public:
        typedef EventList::reverse_iterator reverse_iterator;
        typedef EventList::const_iterator const_iterator;
 
-       ControlList (Parameter id);
+       ControlList (const Parameter& id);
        //ControlList (const XMLNode&, Parameter id);
        ~ControlList();
        
@@ -97,8 +97,8 @@ public:
        void freeze();
        void thaw ();
 
-       const Parameter& parameter() const          { return _parameter; }
-       void             set_parameter(Parameter p) { _parameter = p; }
+       const Parameter& parameter() const                 { return _parameter; }
+       void             set_parameter(const Parameter& p) { _parameter = p; }
 
        EventList::size_type size() const { return _events.size(); }
        bool empty() const { return _events.empty(); }
index ba6e5e5623416e57f3fd232cbdbef2254b6d6e71..73fa5554e6415c46ba114cd249d6367d6ab6e373 100644 (file)
@@ -37,8 +37,8 @@ public:
        ControlSet();
        virtual ~ControlSet() {}
 
-       virtual boost::shared_ptr<Control> control(Evoral::Parameter id, bool create_if_missing=false);
-       virtual boost::shared_ptr<const Control> control(Evoral::Parameter id) const;
+       virtual boost::shared_ptr<Control> control(const Parameter& id, bool create_if_missing=false);
+       virtual boost::shared_ptr<const Control> control(const Parameter& id) const;
        
        virtual boost::shared_ptr<Control> control_factory(boost::shared_ptr<ControlList> list) const;
        virtual boost::shared_ptr<ControlList> control_list_factory(const Parameter& param) const;
@@ -51,7 +51,7 @@ public:
 
        virtual bool find_next_event(nframes_t start, nframes_t end, ControlEvent& ev) const;
        
-       virtual float default_parameter_value(Parameter param) { return 1.0f; }
+       virtual float default_parameter_value(const Parameter& param) { return 1.0f; }
 
        virtual void clear();
 
index c21a86264df2dfff98d01f2d3024223bcd6ebe68..e2bfdc3fb089ab3d574da6260da9592c003bcb39 100644 (file)
@@ -23,29 +23,34 @@ namespace Evoral {
 namespace MIDI {
 
 struct ContinuousController : public Parameter {
-       ContinuousController(uint32_t cc_type, uint32_t channel, uint32_t controller)
-          : Parameter(cc_type, controller, channel) { set_range(*this); }
-       static void set_range(Parameter& p) { p.set_range(0.0, 127.0, 0.0); }
+       ContinuousController(uint32_t cc_type, uint8_t channel, uint32_t controller)
+               : Parameter(cc_type, channel, controller) {}
 };
 
 struct ProgramChange : public Parameter {
-       ProgramChange(uint32_t pc_type, uint32_t channel)
-          : Parameter(pc_type, 0, channel) { set_range(*this); }
-       static void set_range(Parameter& p) { p.set_range(0.0, 127.0, 0.0); }
+       ProgramChange(uint32_t pc_type, uint8_t channel) : Parameter(pc_type, 0, channel) {}
 };
 
 struct ChannelAftertouch : public Parameter {
-       ChannelAftertouch(uint32_t ca_type, uint32_t channel)
-          : Parameter(ca_type, 0, channel) { set_range(*this); }
-       static void set_range(Parameter& p) { p.set_range(0.0, 127.0, 0.0); }
+       ChannelAftertouch(uint32_t ca_type, uint32_t channel) : Parameter(ca_type, 0, channel) {}
 };
 
 struct PitchBender : public Parameter {
-       PitchBender(uint32_t pb_type, uint32_t channel)
-          : Parameter(pb_type, 0, channel) { set_range(*this); }
-       static void set_range(Parameter& p) { p.set_range(0.0, 16383.0, 8192.0); }
+       PitchBender(uint32_t pb_type, uint32_t channel) : Parameter(pb_type, 0, channel) {}
 };
 
+inline static void controller_range(double& min, double& max, double& normal) {
+       min = 0.0;
+       normal = 0.0;
+       max = 127.0;
+}
+
+inline static void bender_range(double& min, double& max, double& normal) {
+       min = 0.0;
+       normal = 8192.0;
+       max = 16383.0;
+}
+
 } // namespace MIDI
 } // namespace Evoral
 
index ae405ec0398eb04101559a663b69fd77ab1ebcac..301a432bd0109726760ba6dfd03f90ea50eb59b5 100644 (file)
 #define EVORAL_PARAMETER_HPP
 
 #include <string>
+#include <map>
+#include <boost/shared_ptr.hpp>
 #include <boost/format.hpp>
+#include <iostream>
 
 namespace Evoral {
 
@@ -37,19 +40,27 @@ namespace Evoral {
 class Parameter
 {
 public:
-       Parameter(uint32_t type, uint32_t id, int8_t channel=0,
-                       double min=0.0f, double max=0.0f, double def=0.0f)
-               : _type(type), _id(id), _channel(channel), _min(min), _max(max), _normal(def)
+       Parameter(uint32_t type, uint8_t channel, uint32_t id=0)
+               : _type(type), _id(id), _channel(channel)
        {}
        
-       //Parameter(const std::string& str);
+       Parameter(const std::string& str) {
+               int channel;
+               if (sscanf(str.c_str(), "%d_c%d_n%d", &_type, &channel, &_id) == 3) {
+                       if (channel >= 0 && channel <= 127) {
+                               _channel = channel;
+                       } else {
+                               std::cerr << "WARNING: Channel out of range: " << channel << std::endl;
+                       }
+               }
+               std::cerr << "WARNING: Unable to create parameter from string: " << str << std::endl;
+       }
 
        inline uint32_t type()    const { return _type; }
        inline uint32_t id()      const { return _id; }
        inline uint8_t  channel() const { return _channel; }
 
-       /**
-        * Equivalence operator
+       /** Equivalence operator
         * It is obvious from the definition that this operator
         * is transitive, as required by stict weak ordering
         * (see: http://www.sgi.com/tech/stl/StrictWeakOrdering.html)
@@ -101,18 +112,37 @@ public:
        inline operator bool() const { return (_type != 0); }
        
        virtual std::string symbol() const {
-               return (boost::format("%1%_c%2%_n%3%\n") % _type % _channel % _id).str();
+               return (boost::format("%1%_c%2%_n%3%") % _type % (int)_channel % _id).str();
        }
+
+       /** Not used in indentity/comparison */
+       struct Metadata {
+               Metadata(double low=0.0, double high=1.0, double mid=0.0)
+                       : min(low), max(high), normal(mid)
+               {}
+               double min;
+               double max;
+               double normal;
+       };
        
-       inline void set_range(double min, double max, double normal) {
-               _min = min;
-               _max = max;
-               _normal = normal;
+       inline static void set_range(uint32_t type, double min, double max, double normal) {
+               _type_metadata[type] = Metadata(min, max, normal);
        }
        
-       inline const double min()    const { return _min; }
-       inline const double max()    const { return _max; }
-       inline const double normal() const { return _normal; }
+       inline void set_range(double min, double max, double normal) {
+               _metadata = boost::shared_ptr<Metadata>(new Metadata(min, max, normal));
+       }
+
+       inline Metadata& metadata() const {
+               if (_metadata)
+                       return *_metadata.get();
+               else
+                       return _type_metadata[_type];
+       }
+
+       inline const double min()    const { return metadata().min; }
+       inline const double max()    const { return metadata().max; }
+       inline const double normal() const { return metadata().normal; }
 
 protected:
        // Default copy constructor is ok
@@ -121,11 +151,11 @@ protected:
        uint32_t _type;
        uint32_t _id;
        uint8_t  _channel;
+       
+       boost::shared_ptr<Metadata> _metadata;
 
-       // Metadata (not used in comparison)
-       double _min;
-       double _max;
-       double _normal;
+       typedef std::map<uint32_t, Metadata> TypeMetadata;
+       static TypeMetadata _type_metadata;
 };
 
 
index 0f1de2a7af04496b38128522125a757930228943..10a61704ed1a835f282e8e26e0a97797e7cefea1 100644 (file)
@@ -177,7 +177,7 @@ private:
        
        void append_note_on_unlocked(uint8_t chan, double time, uint8_t note, uint8_t velocity);
        void append_note_off_unlocked(uint8_t chan, double time, uint8_t note);
-       void append_control_unlocked(Parameter param, double time, double value);
+       void append_control_unlocked(const Parameter& param, double time, double value);
 
        mutable Glib::RWLock _lock;
 
index 8efc2a66591507d28fdac9b9e3d54f05d9fac08b..d23f6c3c9a931daa584ab02133a9ecac64519e39 100644 (file)
@@ -22,6 +22,8 @@
 
 namespace Evoral {
 
+Parameter::TypeMetadata Parameter::_type_metadata;
+
 Control::Control(boost::shared_ptr<ControlList> list)
        : _list(list)
        , _user_value(list->default_value())
@@ -72,7 +74,7 @@ Control::set_list(boost::shared_ptr<ControlList> list)
 }
 
        
-Parameter
+const Parameter&
 Control::parameter() const
 {
        return _list->parameter();
index 8f6ea1872fae6011f20ff669523b6424546e33d4..62c49a97e6f2175460391a171afb6892d07100f9 100644 (file)
@@ -33,7 +33,7 @@ inline bool event_time_less_than (ControlEvent* a, ControlEvent* b)
 }
 
 
-ControlList::ControlList (Parameter id)
+ControlList::ControlList (const Parameter& id)
        : _parameter(id)
        , _interpolation(Linear)
        , _curve(new Curve(*this))
index 93a0b0ef2523db5c1fe3226b9327a73058bd1ba6..5aacff598d6792ab7aa2d029bf9ce2b6b3d3966b 100644 (file)
@@ -53,7 +53,7 @@ ControlSet::what_has_data (set<Parameter>& s) const
  * for \a parameter does not exist.
  */
 boost::shared_ptr<Control>
-ControlSet::control (Parameter parameter, bool create_if_missing)
+ControlSet::control (const Parameter& parameter, bool create_if_missing)
 {
        Controls::iterator i = _controls.find(parameter);
 
@@ -73,7 +73,7 @@ ControlSet::control (Parameter parameter, bool create_if_missing)
 }
 
 boost::shared_ptr<const Control>
-ControlSet::control (Parameter parameter) const
+ControlSet::control (const Parameter& parameter) const
 {
        Controls::const_iterator i = _controls.find(parameter);
 
index 81502fdb5ff6016499d74d028e61814ac7e841e6..4880b5a04dcd0c5b7d741fa26ce753058637f874 100644 (file)
@@ -587,7 +587,7 @@ void Sequence::append_note_off_unlocked(uint8_t chan, double time,
        }
 }
 
-void Sequence::append_control_unlocked(Parameter param, double time, double value)
+void Sequence::append_control_unlocked(const Parameter& param, double time, double value)
 {
        control(param, true)->list()->rt_add(time, value);
 }