From 05476514c0a6831cc72ea7ffb7dfad112329838d Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sun, 5 Jan 2025 11:49:11 -0700 Subject: [PATCH] Add concept of insensitive automation lines for use in MIDI cue editor This commit also includes auto-fication of several loops It also includes a new concept: control points inherit line color. This is enabled by default, so control points just take their color from their parent line. More work is needed here to handle selection colors --- gtk2_ardour/automation_line.cc | 103 +++++++++++++++++++++++++-------- gtk2_ardour/automation_line.h | 11 +++- gtk2_ardour/control_point.cc | 17 ++++-- gtk2_ardour/midi_cue_view.cc | 8 +-- 4 files changed, 106 insertions(+), 33 deletions(-) diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 1a8e3b4574..e1033d3877 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -109,6 +109,8 @@ AutomationLine::AutomationLine (const string& name, , _maximum_time (timepos_t::max (al->time_domain())) , _fill (false) , _desc (desc) + , _control_points_inherit_color (true) + , _sensitive (true) { group = new ArdourCanvas::Container (&parent, ArdourCanvas::Duple(0, 1.5)); CANVAS_DEBUG_NAME (group, "automation line group"); @@ -133,13 +135,29 @@ AutomationLine::~AutomationLine () { delete group; // deletes child items - for (std::vector::iterator i = control_points.begin(); i != control_points.end(); i++) { - (*i)->unset_item (); - delete *i; + for (auto & cp :control_points) { + cp->unset_item (); + delete cp; } control_points.clear (); } +void +AutomationLine::set_sensitive (bool yn) +{ + _sensitive = yn; + + set_line_color (_line_color); + + for (auto & cp : control_points) { + if (yn) { + cp->show(); + } else { + cp->hide (); + } + } +} + timepos_t AutomationLine::get_origin() const { @@ -260,8 +278,8 @@ AutomationLine::set_height (guint32 h) double bsz = control_point_box_size(); - for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { - (*i)->set_size (bsz); + for (auto & cp : control_points) { + cp->set_size (bsz); } if (_fill) { @@ -274,23 +292,62 @@ AutomationLine::set_height (guint32 h) } void -AutomationLine::set_line_color (string color_name, std::string color_mod) +AutomationLine::set_line_color (string const & color_name, string color_mod) { - _line_color = color_name; - _line_color_mod = color_mod; + _line_color = color_name; - uint32_t color = UIConfiguration::instance().color (color_name); - line->set_outline_color (color); + if (_sensitive) { + line->set_outline_color (UIConfiguration::instance().color (color_name)); + } else { + line->set_outline_color (UIConfiguration::instance().color (color_name + " insensitive")); + } + + /* The fill color is used to shade the area under some + * automation lines + */ Gtkmm2ext::SVAModifier mod = UIConfiguration::instance().modifier (color_mod.empty () ? "automation line fill" : color_mod); + line->set_fill_color ((line->outline_color() & 0xffffff00) + (mod.a() * 255)); - line->set_fill_color ((color & 0xffffff00) + mod.a() * 255); + if (_control_points_inherit_color) { + for (auto & cp : control_points) { + cp->set_color (); + } + } +} + +uint32_t +AutomationLine::get_line_fill_color() const +{ + return line->fill_color (); } uint32_t AutomationLine::get_line_color() const { - return UIConfiguration::instance().color (_line_color); + return line->outline_color (); +} + +uint32_t +AutomationLine::get_line_selected_color() const +{ + return line->outline_color (); +} + +bool +AutomationLine::control_points_inherit_color () const +{ + return _control_points_inherit_color; +} + +void +AutomationLine::set_control_points_inherit_color (bool yn) +{ + _control_points_inherit_color = yn; + + for (auto & cp : control_points) { + cp->set_color (); + } } ControlPoint* @@ -988,12 +1045,12 @@ AutomationLine::get_inverted_selectables (Selection&, list& /*resul void AutomationLine::set_selected_points (PointSelection const & points) { - for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { - (*i)->set_selected (false); + for (auto & cp : control_points) { + cp->set_selected (false); } - for (PointSelection::const_iterator i = points.begin(); i != points.end(); ++i) { - (*i)->set_selected (true); + for (auto & p : points) { + p->set_selected (true); } if (points.empty()) { @@ -1008,9 +1065,9 @@ AutomationLine::set_selected_points (PointSelection const & points) void AutomationLine::set_colors () { - set_line_color (_line_color, _line_color_mod); - for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { - (*i)->set_color (); + set_line_color (_line_color); + for (auto & cp : control_points) { + cp->set_color (); } } @@ -1043,8 +1100,8 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) uint32_t np; if (events.empty()) { - for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { - delete *i; + for (auto & cp : control_points) { + delete cp; } control_points.clear (); line->hide(); @@ -1054,8 +1111,8 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) /* hide all existing points, and the line */ - for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { - (*i)->hide(); + for (auto & cp : control_points) { + cp->hide(); } line->hide (); diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index 03fa06aaea..9dd74c549d 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -82,6 +82,9 @@ public: ArdourCanvas::Rectangle* drag_base() const { return _drag_base; } + void set_sensitive (bool); + bool sensitive() const { return _sensitive; } + void queue_reset (); void reset (); void clear (); @@ -110,8 +113,12 @@ public: bool visible() const { return _visible != VisibleAspects(0); } guint32 height() const { return _height; } - void set_line_color (std::string color, std::string mod = ""); + void set_line_color (std::string const & color, std::string color_mode = std::string()); uint32_t get_line_color() const; + uint32_t get_line_fill_color() const; + uint32_t get_line_selected_color() const; + bool control_points_inherit_color () const; + void set_control_points_inherit_color (bool); void set_visibility (VisibleAspects); void add_visibility (VisibleAspects); @@ -260,6 +267,8 @@ private: bool _fill; const ARDOUR::ParameterDescriptor _desc; + bool _control_points_inherit_color; + bool _sensitive; friend class AudioRegionGainLine; friend class RegionFxLine; diff --git a/gtk2_ardour/control_point.cc b/gtk2_ardour/control_point.cc index 581e922f81..16b2eb4870 100644 --- a/gtk2_ardour/control_point.cc +++ b/gtk2_ardour/control_point.cc @@ -120,12 +120,19 @@ ControlPoint::reset (double x, double y, AutomationList::iterator mi, uint32_t v void ControlPoint::set_color () { - if (_selected) { - _item->set_outline_color(UIConfiguration::instance().color ("control point selected outline"));; - _item->set_fill_color(UIConfiguration::instance().color ("control point selected fill")); + if (_line.control_points_inherit_color()) { + + _item->set_outline_color(_line.get_line_color()); + _item->set_fill_color(_line.get_line_fill_color ()); + } else { - _item->set_outline_color(UIConfiguration::instance().color ("control point outline")); - _item->set_fill_color(UIConfiguration::instance().color ("control point fill")); + if (_selected) { + _item->set_outline_color(UIConfiguration::instance().color ("control point selected outline"));; + _item->set_fill_color(UIConfiguration::instance().color ("control point selected fill")); + } else { + _item->set_outline_color(UIConfiguration::instance().color ("control point outline")); + _item->set_fill_color(UIConfiguration::instance().color ("control point fill")); + } } } diff --git a/gtk2_ardour/midi_cue_view.cc b/gtk2_ardour/midi_cue_view.cc index d4bbcb2e65..ef2179658e 100644 --- a/gtk2_ardour/midi_cue_view.cc +++ b/gtk2_ardour/midi_cue_view.cc @@ -348,7 +348,7 @@ MidiCueView::update_automation_display (Evoral::Parameter const & param, Selecti automation_group, ac->alist(), ac->desc())); - line->set_line_color ("midi line inactive"); + line->set_sensitive (false); AutomationDisplayState cad (ac, line, true); @@ -414,7 +414,7 @@ void MidiCueView::unset_active_automation () { for (CueAutomationMap::iterator i = automation_map.begin(); i != automation_map.end(); ++i) { - i->second.line->set_line_color ("midi line inactive"); + i->second.line->set_sensitive (false); } active_automation = nullptr; @@ -428,11 +428,11 @@ MidiCueView::internal_set_active_automation (Evoral::Parameter const & param) for (CueAutomationMap::iterator i = automation_map.begin(); i != automation_map.end(); ++i) { if (i->first == param) { - i->second.line->set_line_color ("gain line"); + i->second.line->set_sensitive (true); active_automation = &i->second; exists = true; } else { - i->second.line->set_line_color ("midi line inactive"); + i->second.line->set_sensitive (false); } }