diff options
-rw-r--r-- | gtk2_ardour/automation_line.cc | 45 | ||||
-rw-r--r-- | gtk2_ardour/automation_line.h | 66 | ||||
-rw-r--r-- | gtk2_ardour/midi_automation_line.cc | 49 | ||||
-rw-r--r-- | gtk2_ardour/midi_automation_line.h | 10 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_patch_manager.h | 2 | ||||
-rw-r--r-- | libs/ardour/instrument_info.cc | 2 | ||||
-rw-r--r-- | libs/midi++2/midi++/midnam_patch.h | 66 | ||||
-rw-r--r-- | libs/midi++2/midnam_patch.cc | 152 | ||||
-rw-r--r-- | libs/midi++2/test/MidnamTest.cpp | 11 |
9 files changed, 323 insertions, 80 deletions
diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 9fe1e0fa19..a4d58cb531 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -70,8 +70,8 @@ using namespace Editing; * This will not be deleted by AutomationLine. */ AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanvas::Group& parent, - boost::shared_ptr<AutomationList> al, - Evoral::TimeConverter<double, framepos_t>* converter) + boost::shared_ptr<AutomationList> al, + Evoral::TimeConverter<double, framepos_t>* converter) : trackview (tv) , _name (name) , alist (al) @@ -192,7 +192,7 @@ AutomationLine::control_point_box_size () { if (alist->interpolation() == AutomationList::Discrete) { return max((_height*4.0) / (double)(alist->parameter().max() - alist->parameter().min()), - 4.0); + 4.0); } if (_height > TimeAxisView::preset_height (HeightLarger)) { @@ -270,8 +270,7 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y) trackview.editor().session()->begin_reversible_command (_("automation event move")); trackview.editor().session()->add_command ( - new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0) - ); + new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0)); cp.move_to (x, y, ControlPoint::Full); @@ -288,8 +287,7 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y) update_pending = false; trackview.editor().session()->add_command ( - new MementoCommand<AutomationList> (memento_command_binder(), 0, &alist->get_state()) - ); + new MementoCommand<AutomationList> (memento_command_binder(), 0, &alist->get_state())); trackview.editor().session()->commit_reversible_command (); trackview.editor().session()->set_dirty (); @@ -453,8 +451,7 @@ AutomationLine::start_drag_single (ControlPoint* cp, double x, float fraction) { trackview.editor().session()->begin_reversible_command (_("automation event move")); trackview.editor().session()->add_command ( - new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0) - ); + new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0)); _drag_points.clear (); _drag_points.push_back (cp); @@ -480,8 +477,7 @@ AutomationLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction) { trackview.editor().session()->begin_reversible_command (_("automation range move")); trackview.editor().session()->add_command ( - new MementoCommand<AutomationList> (memento_command_binder (), &get_state(), 0) - ); + new MementoCommand<AutomationList> (memento_command_binder (), &get_state(), 0)); _drag_points.clear (); @@ -501,8 +497,7 @@ AutomationLine::start_drag_multiple (list<ControlPoint*> cp, float fraction, XML { trackview.editor().session()->begin_reversible_command (_("automation range move")); trackview.editor().session()->add_command ( - new MementoCommand<AutomationList> (memento_command_binder(), state, 0) - ); + new MementoCommand<AutomationList> (memento_command_binder(), state, 0)); _drag_points = cp; start_drag_common (0, fraction); @@ -740,8 +735,7 @@ AutomationLine::end_drag (bool with_push, uint32_t final_index) update_pending = false; trackview.editor().session()->add_command ( - new MementoCommand<AutomationList>(memento_command_binder (), 0, &alist->get_state()) - ); + new MementoCommand<AutomationList>(memento_command_binder (), 0, &alist->get_state())); trackview.editor().session()->set_dirty (); did_push = false; @@ -845,8 +839,7 @@ AutomationLine::remove_point (ControlPoint& cp) alist->erase (cp.model()); trackview.editor().session()->add_command( - new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()) - ); + new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state())); trackview.editor().session()->commit_reversible_command (); trackview.editor().session()->set_dirty (); @@ -958,7 +951,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) if (isnan (tx) || isnan (ty)) { warning << string_compose (_("Ignoring illegal points on AutomationLine \"%1\""), - _name) << endmsg; + _name) << endmsg; continue; } @@ -1064,8 +1057,7 @@ AutomationLine::clear () alist->clear(); trackview.editor().session()->add_command ( - new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state()) - ); + new MementoCommand<AutomationList> (memento_command_binder (), &before, &alist->get_state())); } void @@ -1161,8 +1153,8 @@ AutomationLine::view_to_model_coord_y (double& y) const y = max (0.0, y); y = min (2.0, y); } else if (alist->parameter().type() == PanAzimuthAutomation || - alist->parameter().type() == PanElevationAutomation || - alist->parameter().type() == PanWidthAutomation) { + alist->parameter().type() == PanElevationAutomation || + alist->parameter().type() == PanWidthAutomation) { y = 1.0 - y; } else if (alist->parameter().type() == PluginAutomation) { y = y * (double)(alist->get_max_y()- alist->get_min_y()) + alist->get_min_y(); @@ -1179,8 +1171,8 @@ AutomationLine::model_to_view_coord (double& x, double& y) const alist->parameter().type() == EnvelopeAutomation) { y = gain_to_slider_position_with_max (y, Config->get_max_gain()); } else if (alist->parameter().type() == PanAzimuthAutomation || - alist->parameter().type() == PanElevationAutomation || - alist->parameter().type() == PanWidthAutomation) { + alist->parameter().type() == PanElevationAutomation || + alist->parameter().type() == PanWidthAutomation) { // vertical coordinate axis reversal y = 1.0 - y; } else if (alist->parameter().type() == PluginAutomation) { @@ -1206,7 +1198,7 @@ AutomationLine::interpolation_changed (AutomationList::InterpolationStyle style) void AutomationLine::add_visible_control_point (uint32_t view_index, uint32_t pi, double tx, double ty, - AutomationList::iterator model, uint32_t npoints) + AutomationList::iterator model, uint32_t npoints) { ControlPoint::ShapeType shape; @@ -1259,8 +1251,7 @@ AutomationLine::connect_to_list () alist->StateChanged.connect (_list_connections, invalidator (*this), boost::bind (&AutomationLine::list_changed, this), gui_context()); alist->InterpolationChanged.connect ( - _list_connections, invalidator (*this), boost::bind (&AutomationLine::interpolation_changed, this, _1), gui_context() - ); + _list_connections, invalidator (*this), boost::bind (&AutomationLine::interpolation_changed, this, _1), gui_context()); } MementoCommandBinder<AutomationList>* diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index bb1e927ad5..3583ecdd71 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -52,7 +52,7 @@ class Selection; /** A GUI representation of an ARDOUR::AutomationList */ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible { - public: +public: enum VisibleAspects { Line = 0x1, ControlPoints = 0x2, @@ -60,8 +60,8 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible }; AutomationLine (const std::string& name, TimeAxisView&, ArdourCanvas::Group&, - boost::shared_ptr<ARDOUR::AutomationList>, - Evoral::TimeConverter<double, ARDOUR::framepos_t>* converter = 0); + boost::shared_ptr<ARDOUR::AutomationList>, + Evoral::TimeConverter<double, ARDOUR::framepos_t>* converter = 0); virtual ~AutomationLine (); void queue_reset (); @@ -76,11 +76,11 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible bool control_points_adjacent (double xval, uint32_t& before, uint32_t& after); /* dragging API */ - virtual void start_drag_single (ControlPoint*, double, float); - virtual void start_drag_line (uint32_t, uint32_t, float); - virtual void start_drag_multiple (std::list<ControlPoint*>, float, XMLNode *); - virtual std::pair<double, float> drag_motion (double, float, bool, bool with_push, uint32_t& final_index); - virtual void end_drag (bool with_push, uint32_t final_index); + virtual void start_drag_single (ControlPoint*, double, float); + virtual void start_drag_line (uint32_t, uint32_t, float); + virtual void start_drag_multiple (std::list<ControlPoint*>, float, XMLNode *); + virtual std::pair<double, float> drag_motion (double, float, bool, bool with_push, uint32_t& final_index); + virtual void end_drag (bool with_push, uint32_t final_index); ControlPoint* nth (uint32_t); ControlPoint const * nth (uint32_t) const; @@ -108,10 +108,10 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible ArdourCanvas::Item& parent_group() const { return _parent_group; } ArdourCanvas::Item& grab_item() const { return *line; } - std::string get_verbose_cursor_string (double) const; - std::string get_verbose_cursor_relative_string (double, double) const; + virtual std::string get_verbose_cursor_string (double) const; + std::string get_verbose_cursor_relative_string (double, double) const; std::string fraction_to_string (double) const; - std::string fraction_to_relative_string (double, double) const; + std::string fraction_to_relative_string (double, double) const; double string_to_fraction (std::string const &) const; void view_to_model_coord (double& x, double& y) const; void view_to_model_coord_y (double &) const; @@ -141,7 +141,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible std::pair<ARDOUR::framepos_t, ARDOUR::framepos_t> get_point_x_range () const; void set_maximum_time (ARDOUR::framecnt_t); - ARDOUR::framecnt_t maximum_time () const { + ARDOUR::framecnt_t maximum_time () const { return _maximum_time; } @@ -150,7 +150,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible framepos_t session_position (ARDOUR::AutomationList::const_iterator) const; - protected: +protected: std::string _name; guint32 _height; @@ -163,12 +163,12 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible VisibleAspects _visible; - bool _uses_gain_mapping; - bool terminal_points_can_slide; - bool update_pending; - bool have_timeout; - bool no_draw; - bool _is_boolean; + bool _uses_gain_mapping; + bool terminal_points_can_slide; + bool update_pending; + bool have_timeout; + bool no_draw; + bool _is_boolean; /** true if we did a push at any point during the current drag */ bool did_push; @@ -178,26 +178,26 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible ArdourCanvas::Points line_points; /* coordinates for canvas line */ std::vector<ControlPoint*> control_points; /* visible control points */ - class ContiguousControlPoints : public std::list<ControlPoint*> { - public: - ContiguousControlPoints (AutomationLine& al); - double clamp_dx (double dx); - void move (double dx, double dy); - void compute_x_bounds (); - private: - AutomationLine& line; - double before_x; - double after_x; + class ContiguousControlPoints : public std::list<ControlPoint*> { +public: + ContiguousControlPoints (AutomationLine& al); + double clamp_dx (double dx); + void move (double dx, double dy); + void compute_x_bounds (); +private: + AutomationLine& line; + double before_x; + double after_x; }; - friend class ContiguousControlPoints; + friend class ContiguousControlPoints; typedef boost::shared_ptr<ContiguousControlPoints> CCP; - std::vector<CCP> contiguous_points; + std::vector<CCP> contiguous_points; void sync_model_with_view_point (ControlPoint&); void sync_model_with_view_points (std::list<ControlPoint*>); - void start_drag_common (double, float); + void start_drag_common (double, float); virtual void change_model (ARDOUR::AutomationList::iterator, double x, double y); @@ -206,7 +206,7 @@ class AutomationLine : public sigc::trackable, public PBD::StatefulDestructible virtual bool event_handler (GdkEvent*); - private: +private: std::list<ControlPoint*> _drag_points; ///< points we are dragging std::list<ControlPoint*> _push_points; ///< additional points we are dragging if "push" is enabled bool _drag_had_movement; ///< true if the drag has seen movement, otherwise false diff --git a/gtk2_ardour/midi_automation_line.cc b/gtk2_ardour/midi_automation_line.cc index 359c516485..971944266f 100644 --- a/gtk2_ardour/midi_automation_line.cc +++ b/gtk2_ardour/midi_automation_line.cc @@ -18,7 +18,11 @@ */ #include "ardour/midi_automation_list_binder.h" +#include "midi++/midnam_patch.h" #include "midi_automation_line.h" +#include "midi_time_axis.h" + +#include "i18n.h" using namespace std; @@ -30,9 +34,9 @@ MidiAutomationLine::MidiAutomationLine ( boost::shared_ptr<ARDOUR::MidiRegion> region, Evoral::Parameter parameter, Evoral::TimeConverter<double, ARDOUR::framepos_t>* converter) - : AutomationLine (name, tav, group, list, converter) - , _region (region) - , _parameter (parameter) + : AutomationLine (name, tav, group, list, converter) + , _region (region) + , _parameter (parameter) { } @@ -42,3 +46,42 @@ MidiAutomationLine::memento_command_binder () { return new ARDOUR::MidiAutomationListBinder (_region->midi_source(), _parameter); } + +string +MidiAutomationLine::get_verbose_cursor_string (double fraction) const +{ + using namespace MIDI::Name; + + if (_parameter.type() != ARDOUR::MidiCCAutomation) { + return AutomationLine::get_verbose_cursor_string(fraction); + } + + MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(trackview.get_parent()); + if (!mtv) { + return AutomationLine::get_verbose_cursor_string(fraction); + } + + boost::shared_ptr<MasterDeviceNames> device_names(mtv->get_device_names()); + if (!device_names) { + return AutomationLine::get_verbose_cursor_string(fraction); + } + + const std::string& device_mode = mtv->gui_property(X_("midnam-custom-device-mode")); + const uint8_t channel = mtv->get_channel_for_add(); + + boost::shared_ptr<const ValueNameList> value_names = device_names->value_name_list_by_control( + device_mode, channel, _parameter.id()); + if (!value_names) { + return AutomationLine::get_verbose_cursor_string(fraction); + } + + const uint16_t cc_value = floor(std::max(std::min(fraction * 127.0, 127.0), 0.0)); + + boost::shared_ptr<const Value> value = value_names->max_value_below(cc_value); + if (!value) { + return AutomationLine::get_verbose_cursor_string(fraction); + } + + return value->name(); +} + diff --git a/gtk2_ardour/midi_automation_line.h b/gtk2_ardour/midi_automation_line.h index aafe966028..df4db06c2c 100644 --- a/gtk2_ardour/midi_automation_line.h +++ b/gtk2_ardour/midi_automation_line.h @@ -27,13 +27,15 @@ class MidiAutomationLine : public AutomationLine { public: MidiAutomationLine (const std::string&, TimeAxisView&, ArdourCanvas::Group&, - boost::shared_ptr<ARDOUR::AutomationList>, - boost::shared_ptr<ARDOUR::MidiRegion>, - Evoral::Parameter, - Evoral::TimeConverter<double, ARDOUR::framepos_t>* converter = 0); + boost::shared_ptr<ARDOUR::AutomationList>, + boost::shared_ptr<ARDOUR::MidiRegion>, + Evoral::Parameter, + Evoral::TimeConverter<double, ARDOUR::framepos_t>* converter = 0); MementoCommandBinder<ARDOUR::AutomationList>* memento_command_binder (); + virtual std::string get_verbose_cursor_string (double) const; + private: boost::shared_ptr<ARDOUR::MidiRegion> _region; Evoral::Parameter _parameter; diff --git a/libs/ardour/ardour/midi_patch_manager.h b/libs/ardour/ardour/midi_patch_manager.h index e9751c6956..cd898aa00f 100644 --- a/libs/ardour/ardour/midi_patch_manager.h +++ b/libs/ardour/ardour/midi_patch_manager.h @@ -72,7 +72,7 @@ public: boost::shared_ptr<MIDI::Name::MasterDeviceNames> master_device = master_device_by_model(model); if (master_device != 0 && custom_device_mode != "") { - return master_device->channel_name_set_by_device_mode_and_channel(custom_device_mode, channel); + return master_device->channel_name_set_by_channel(custom_device_mode, channel); } else { return boost::shared_ptr<ChannelNameSet>(); } diff --git a/libs/ardour/instrument_info.cc b/libs/ardour/instrument_info.cc index 725dc3b5e9..d6c18ebd4d 100644 --- a/libs/ardour/instrument_info.cc +++ b/libs/ardour/instrument_info.cc @@ -119,7 +119,7 @@ InstrumentInfo::get_controller_name (Evoral::Parameter param) const } boost::shared_ptr<ChannelNameSet> chan_names( - dev_names->channel_name_set_by_device_mode_and_channel( + dev_names->channel_name_set_by_channel( external_instrument_mode, param.channel())); if (!chan_names) { return ""; diff --git a/libs/midi++2/midi++/midnam_patch.h b/libs/midi++2/midi++/midnam_patch.h index d67543429a..9b2a611d9e 100644 --- a/libs/midi++2/midi++/midnam_patch.h +++ b/libs/midi++2/midi++/midnam_patch.h @@ -263,6 +263,55 @@ private: Notes _notes; }; +class LIBMIDIPP_API Value +{ +public: + Value() {} + Value(const uint16_t number, + const std::string& name) + : _number(number) + , _name(name) + {} + + uint16_t number() const { return _number; } + const std::string& name() const { return _name; } + + void set_number(uint16_t number) { _number = number; } + void set_name(const std::string& name) { _name = name; } + + XMLNode& get_state(void); + int set_state(const XMLTree&, const XMLNode&); + +private: + uint16_t _number; + std::string _name; +}; + +class LIBMIDIPP_API ValueNameList +{ +public: + typedef std::map<uint16_t, boost::shared_ptr<Value> > Values; + + ValueNameList() {} + ValueNameList(const std::string& name) : _name(name) {} + + const std::string& name() const { return _name; } + + void set_name(const std::string& name) { _name = name; } + + boost::shared_ptr<const Value> value(uint16_t num) const; + boost::shared_ptr<const Value> max_value_below(uint16_t num) const; + + const Values& values() const { return _values; } + + XMLNode& get_state(void); + int set_state(const XMLTree&, const XMLNode&); + +private: + std::string _name; + Values _values; +}; + class LIBMIDIPP_API Control { public: @@ -279,6 +328,9 @@ public: uint16_t number() const { return _number; } const std::string& name() const { return _name; } + const std::string& value_name_list_name() const { return _value_name_list_name; } + boost::shared_ptr<const ValueNameList> value_name_list() const { return _value_name_list; } + void set_type(const std::string& type) { _type = type; } void set_number(uint16_t number) { _number = number; } void set_name(const std::string& name) { _name = name; } @@ -290,6 +342,9 @@ private: std::string _type; uint16_t _number; std::string _name; + + std::string _value_name_list_name; ///< Global, UsesValueNameList + boost::shared_ptr<ValueNameList> _value_name_list; ///< Local, ValueNameList }; class LIBMIDIPP_API ControlNameList @@ -353,6 +408,7 @@ public: typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> > ChannelNameSets; typedef std::map<std::string, boost::shared_ptr<NoteNameList> > NoteNameLists; typedef std::map<std::string, boost::shared_ptr<ControlNameList> > ControlNameLists; + typedef std::map<std::string, boost::shared_ptr<ValueNameList> > ValueNameLists; typedef std::map<std::string, PatchNameList> PatchNameLists; MasterDeviceNames() {}; @@ -365,14 +421,21 @@ public: void set_models(const Models some_models) { _models = some_models; } const ControlNameLists& controls() const { return _control_name_lists; } + const ValueNameLists& values() const { return _value_name_lists; } + + boost::shared_ptr<const ValueNameList> value_name_list_by_control( + const std::string& mode, + uint8_t channel, + uint8_t number); const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; } boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(const std::string& mode_name); - boost::shared_ptr<ChannelNameSet> channel_name_set_by_device_mode_and_channel(const std::string& mode, uint8_t channel); + boost::shared_ptr<ChannelNameSet> channel_name_set_by_channel(const std::string& mode, uint8_t channel); boost::shared_ptr<Patch> find_patch(const std::string& mode, uint8_t channel, const PatchPrimaryKey& key); boost::shared_ptr<ControlNameList> control_name_list(const std::string& name); + boost::shared_ptr<ValueNameList> value_name_list(const std::string& name); boost::shared_ptr<NoteNameList> note_name_list(const std::string& name); boost::shared_ptr<ChannelNameSet> channel_name_set(const std::string& name); @@ -394,6 +457,7 @@ private: NoteNameLists _note_name_lists; PatchNameLists _patch_name_lists; ControlNameLists _control_name_lists; + ValueNameLists _value_name_lists; }; class LIBMIDIPP_API MIDINameDocument diff --git a/libs/midi++2/midnam_patch.cc b/libs/midi++2/midnam_patch.cc index 9dd5bc33db..252804e466 100644 --- a/libs/midi++2/midnam_patch.cc +++ b/libs/midi++2/midnam_patch.cc @@ -251,6 +251,22 @@ Control::set_state (const XMLTree& tree, const XMLNode& node) _number = string_to_int(tree, node.property("Number")->value()); _name = node.property("Name")->value(); + for (XMLNodeList::const_iterator i = node.children().begin(); + i != node.children().end(); ++i) { + if ((*i)->name() == "Values") { + // <Values> has Min and Max properties, but we don't care + for (XMLNodeList::const_iterator j = (*i)->children().begin(); + j != (*i)->children().end(); ++j) { + if ((*j)->name() == "ValueNameList") { + _value_name_list = boost::shared_ptr<ValueNameList>(new ValueNameList()); + _value_name_list->set_state(tree, **j); + } else if ((*j)->name() == "UsesValueNameList") { + _value_name_list_name = (*j)->property("Name")->value(); + } + } + } + } + return 0; } @@ -299,6 +315,91 @@ ControlNameList::control(uint16_t num) const } XMLNode& +Value::get_state (void) +{ + XMLNode* node = new XMLNode("Value"); + node->add_property("Number", _number); + node->add_property("Name", _name); + + return *node; +} + +int +Value::set_state (const XMLTree& tree, const XMLNode& node) +{ + assert(node.name() == "Value"); + _number = string_to_int(tree, node.property("Number")->value()); + _name = node.property("Name")->value(); + + return 0; +} + +XMLNode& +ValueNameList::get_state (void) +{ + XMLNode* node = new XMLNode("ValueNameList"); + node->add_property("Name", _name); + + return *node; +} + +int +ValueNameList::set_state (const XMLTree& tree, const XMLNode& node) +{ + assert(node.name() == "ValueNameList"); + const XMLProperty* name_prop = node.property("Name"); + if (name_prop) { + // May be anonymous if written inline within a single <Control> tag + _name = name_prop->value(); + } + + _values.clear(); + for (XMLNodeList::const_iterator i = node.children().begin(); + i != node.children().end(); ++i) { + if ((*i)->name() == "Value") { + boost::shared_ptr<Value> value(new Value()); + value->set_state (tree, *(*i)); + if (_values.find(value->number()) == _values.end()) { + _values.insert(make_pair(value->number(), value)); + } else { + PBD::warning << string_compose("%1: Duplicate value %2 ignored", + tree.filename(), value->number()) + << endmsg; + } + } + } + + return 0; +} + +boost::shared_ptr<const Value> +ValueNameList::value(uint16_t num) const +{ + Values::const_iterator i = _values.find(num); + if (i != _values.end()) { + return i->second; + } + return boost::shared_ptr<const Value>(); +} + +boost::shared_ptr<const Value> +ValueNameList::max_value_below(uint16_t num) const +{ + Values::const_iterator i = _values.lower_bound(num); + if (i->first == num) { + // Exact match + return i->second; + } else if (i == _values.begin()) { + // No value is < num + return boost::shared_ptr<const Value>(); + } else { + // Found the smallest element >= num, so the previous one is our result + --i; + return i->second; + } +} + +XMLNode& PatchBank::get_state (void) { XMLNode* node = new XMLNode("PatchBank"); @@ -525,6 +626,31 @@ CustomDeviceMode::get_state(void) return *custom_device_mode; } +boost::shared_ptr<const ValueNameList> +MasterDeviceNames::value_name_list_by_control(const std::string& mode, uint8_t channel, uint8_t number) +{ + boost::shared_ptr<ChannelNameSet> chan_names = channel_name_set_by_channel(mode, channel); + if (!chan_names) { + return boost::shared_ptr<const ValueNameList>(); + } + + boost::shared_ptr<ControlNameList> control_names = control_name_list(chan_names->control_list_name()); + if (!control_names) { + return boost::shared_ptr<const ValueNameList>(); + } + + boost::shared_ptr<const Control> control = control_names->control(number); + if (!control) { + return boost::shared_ptr<const ValueNameList>(); + } + + if (!control->value_name_list_name().empty()) { + return value_name_list(control->value_name_list_name()); + } else { + return control->value_name_list(); + } +} + boost::shared_ptr<CustomDeviceMode> MasterDeviceNames::custom_device_mode_by_name(const std::string& mode_name) { @@ -532,7 +658,7 @@ MasterDeviceNames::custom_device_mode_by_name(const std::string& mode_name) } boost::shared_ptr<ChannelNameSet> -MasterDeviceNames::channel_name_set_by_device_mode_and_channel(const std::string& mode, uint8_t channel) +MasterDeviceNames::channel_name_set_by_channel(const std::string& mode, uint8_t channel) { boost::shared_ptr<CustomDeviceMode> cdm = custom_device_mode_by_name(mode); boost::shared_ptr<ChannelNameSet> cns = _channel_name_sets[cdm->channel_name_set_name_by_channel(channel)]; @@ -542,7 +668,7 @@ MasterDeviceNames::channel_name_set_by_device_mode_and_channel(const std::string boost::shared_ptr<Patch> MasterDeviceNames::find_patch(const std::string& mode, uint8_t channel, const PatchPrimaryKey& key) { - boost::shared_ptr<ChannelNameSet> cns = channel_name_set_by_device_mode_and_channel(mode, channel); + boost::shared_ptr<ChannelNameSet> cns = channel_name_set_by_channel(mode, channel); if (!cns) return boost::shared_ptr<Patch>(); return cns->find_patch(key); } @@ -567,6 +693,16 @@ MasterDeviceNames::control_name_list(const std::string& name) return boost::shared_ptr<ControlNameList>(); } +boost::shared_ptr<ValueNameList> +MasterDeviceNames::value_name_list(const std::string& name) +{ + ValueNameLists::const_iterator i = _value_name_lists.find(name); + if (i != _value_name_lists.end()) { + return i->second; + } + return boost::shared_ptr<ValueNameList>(); +} + boost::shared_ptr<NoteNameList> MasterDeviceNames::note_name_list(const std::string& name) { @@ -598,7 +734,7 @@ MasterDeviceNames::note_name(const std::string& mode_name, note_name_list(patch->note_list_name())); if (!note_names) { /* No note names specific to this patch, check the ChannelNameSet */ - boost::shared_ptr<ChannelNameSet> chan_names = channel_name_set_by_device_mode_and_channel( + boost::shared_ptr<ChannelNameSet> chan_names = channel_name_set_by_channel( mode_name, channel); if (chan_names) { note_names = note_name_list(chan_names->note_list_name()); @@ -675,6 +811,16 @@ MasterDeviceNames::set_state(const XMLTree& tree, const XMLNode&) _control_name_lists[control_name_list->name()] = control_name_list; } + // ValueNameLists + boost::shared_ptr<XMLSharedNodeList> value_name_lists = tree.find("/child::MIDINameDocument/child::MasterDeviceNames/child::ValueNameList"); + for (XMLSharedNodeList::iterator i = value_name_lists->begin(); + i != value_name_lists->end(); + ++i) { + boost::shared_ptr<ValueNameList> value_name_list(new ValueNameList()); + value_name_list->set_state (tree, *(*i)); + _value_name_lists[value_name_list->name()] = value_name_list; + } + // global/post-facto PatchNameLists boost::shared_ptr<XMLSharedNodeList> patch_name_lists = tree.find("/child::MIDINameDocument/child::MasterDeviceNames/child::PatchNameList"); for (XMLSharedNodeList::iterator i = patch_name_lists->begin(); diff --git a/libs/midi++2/test/MidnamTest.cpp b/libs/midi++2/test/MidnamTest.cpp index ba96d318c4..d8c89eb011 100644 --- a/libs/midi++2/test/MidnamTest.cpp +++ b/libs/midi++2/test/MidnamTest.cpp @@ -56,11 +56,9 @@ MidnamTest::protools_patchfile_test() } boost::shared_ptr<ChannelNameSet> nameSet1 = - masterDeviceNames->channel_name_set_by_device_mode_and_channel( - modename, 0); + masterDeviceNames->channel_name_set_by_channel(modename, 0); boost::shared_ptr<ChannelNameSet> nameSet2 = - masterDeviceNames->channel_name_set_by_device_mode_and_channel( - modename, 9); + masterDeviceNames->channel_name_set_by_channel(modename, 9); CPPUNIT_ASSERT_EQUAL(ns1, nameSet1->name()); CPPUNIT_ASSERT_EQUAL(ns2, nameSet2->name()); @@ -127,8 +125,7 @@ MidnamTest::yamaha_PSRS900_patchfile_test() CPPUNIT_ASSERT_EQUAL(ns, mode->channel_name_set_name_by_channel(i)); boost::shared_ptr<ChannelNameSet> nameSet = - masterDeviceNames->channel_name_set_by_device_mode_and_channel( - ns, 1); + masterDeviceNames->channel_name_set_by_channel(ns, 1); CPPUNIT_ASSERT_EQUAL(ns, nameSet->name()); @@ -196,7 +193,7 @@ MidnamTest::load_all_midnams_test () boost::shared_ptr<CustomDeviceMode> mode = device->second->custom_device_mode_by_name(modename); CPPUNIT_ASSERT_EQUAL(deviceModeName, mode->name()); - boost::shared_ptr<ChannelNameSet> nameSet = device->second->channel_name_set_by_device_mode_and_channel(modename, 0); + boost::shared_ptr<ChannelNameSet> nameSet = device->second->channel_name_set_by_channel(modename, 0); } } |