diff --git a/libs/ardour/ardour/control_group.h b/libs/ardour/ardour/control_group.h index 712bb792aa..d0afc185e2 100644 --- a/libs/ardour/ardour/control_group.h +++ b/libs/ardour/ardour/control_group.h @@ -35,6 +35,8 @@ namespace ARDOUR { class CoreSelection; +class RouteGroup; +class Stripable; class LIBARDOUR_API ControlGroup : public std::enable_shared_from_this { @@ -47,7 +49,7 @@ class LIBARDOUR_API ControlGroup : public std::enable_shared_from_this, CoreSelection const &, Evoral::Parameter const &, bool (RouteGroup::*group_predicate)() const); int add_control (std::shared_ptr, bool push = false); int remove_control (std::shared_ptr, bool pop = false); diff --git a/libs/ardour/ardour/selection.h b/libs/ardour/ardour/selection.h index 3c1dc21670..599102291e 100644 --- a/libs/ardour/ardour/selection.h +++ b/libs/ardour/ardour/selection.h @@ -73,6 +73,8 @@ class LIBARDOUR_API CoreSelection : public PBD::Stateful { typedef std::vector StripableAutomationControls; void get_stripables (StripableAutomationControls&) const; + void get_stripables_for_op (StripableList&, std::shared_ptr base, bool (RouteGroup::*group_predicate)() const) const; + void get_stripables_for_op (std::shared_ptr, std::shared_ptr base, bool (RouteGroup::*group_predicate)() const) const; XMLNode& get_state () const; int set_state (const XMLNode&, int version); diff --git a/libs/ardour/ardour/solo_mute_release.h b/libs/ardour/ardour/solo_mute_release.h index fea7d197b6..c8b1596936 100644 --- a/libs/ardour/ardour/solo_mute_release.h +++ b/libs/ardour/ardour/solo_mute_release.h @@ -38,9 +38,9 @@ public: void set_exclusive (bool exclusive = true); - void set (std::shared_ptr); - void set (std::shared_ptr); - void set (std::shared_ptr, std::shared_ptr); + void set (std::shared_ptr); + void set (std::shared_ptr); + void set (std::shared_ptr, std::shared_ptr); void set (std::shared_ptr >); void release (Session*, bool mute) const; @@ -49,8 +49,8 @@ private: bool active; bool exclusive; - std::shared_ptr routes_on; - std::shared_ptr routes_off; + std::shared_ptr routes_on; + std::shared_ptr routes_off; std::shared_ptr > port_monitors; }; diff --git a/libs/ardour/control_group.cc b/libs/ardour/control_group.cc index 5dba24c033..06e396b1c0 100644 --- a/libs/ardour/control_group.cc +++ b/libs/ardour/control_group.cc @@ -218,11 +218,11 @@ ControlGroup::set_group_value (std::shared_ptr control, doubl } void -ControlGroup::fill_from_selection (CoreSelection const & sel, Evoral::Parameter const & p) +ControlGroup::fill_from_selection_or_group (std::shared_ptr target, CoreSelection const & sel, Evoral::Parameter const & p, bool (RouteGroup::*group_predicate)() const) { - CoreSelection::StripableAutomationControls stripables; + StripableList sl; - sel.get_stripables (stripables); + sel.get_stripables_for_op (sl, target, group_predicate); /* Very unfortunate that gain control is special cased. Routes do not * call ::add_control() for their gain control, but instead pass it to @@ -231,24 +231,24 @@ ControlGroup::fill_from_selection (CoreSelection const & sel, Evoral::Parameter switch (p.type()) { case GainAutomation: - for (auto & s : stripables) { - std::shared_ptr ac = s.stripable->gain_control (); + for (auto & s : sl) { + std::shared_ptr ac = s->gain_control (); if (ac) { add_control (ac, true); } } break; case TrimAutomation: - for (auto & s : stripables) { - std::shared_ptr ac = s.stripable->trim_control (); + for (auto & s : sl) { + std::shared_ptr ac = s->trim_control (); if (ac) { add_control (ac, true); } } break; default: - for (auto & s : stripables) { - std::shared_ptr ac = s.stripable->automation_control (p, true); + for (auto & s : sl) { + std::shared_ptr ac = s->automation_control (p, true); if (ac) { add_control (ac, true); } diff --git a/libs/ardour/selection.cc b/libs/ardour/selection.cc index 52ecd63356..27ed6421c7 100644 --- a/libs/ardour/selection.cc +++ b/libs/ardour/selection.cc @@ -613,3 +613,41 @@ CoreSelection::selected () const Glib::Threads::RWLock::ReaderLock lm (_lock); return _stripables.size(); } + +void +CoreSelection::get_stripables_for_op (std::shared_ptr sl, std::shared_ptr target, bool (RouteGroup::*group_predicate)() const) const +{ + return get_stripables_for_op (*sl.get(), target, group_predicate); +} + +void +CoreSelection::get_stripables_for_op (StripableList& sl, std::shared_ptr target, bool (RouteGroup::*group_predicate)() const) const +{ + if (_stripables.empty()) { + std::shared_ptr r (std::dynamic_pointer_cast (target)); + + if (r) { + RouteGroup* rg = r->route_group(); + + if (rg && rg->is_active() && (rg->*group_predicate)()) { + for (auto & r : *rg->route_list()) { + sl.push_back (r); + } + } else { + sl.push_back (target); + } + + } else { + /* Base is not a route, use it and it alone */ + sl.push_back (target); + } + + } else { + StripableAutomationControls sc; + get_stripables (sc); + + for (auto & s : sc) { + sl.push_back (s.stripable); + } + } +} diff --git a/libs/ardour/session_rtevents.cc b/libs/ardour/session_rtevents.cc index b9f2b3abbe..9f3d01cd8b 100644 --- a/libs/ardour/session_rtevents.cc +++ b/libs/ardour/session_rtevents.cc @@ -130,25 +130,25 @@ Session::rt_set_controls (std::shared_ptr cl, double val, Contr void Session::prepare_momentary_solo (SoloMuteRelease* smr, bool exclusive, std::shared_ptr route) { - std::shared_ptr routes_on (new RouteList); - std::shared_ptr routes_off (new RouteList); + std::shared_ptr routes_on (new StripableList); + std::shared_ptr routes_off (new StripableList); std::shared_ptr routes = get_routes(); - for (auto const& i : *routes) { + for (auto const & r : *routes) { #ifdef MIXBUS - if (route && (0 == route->mixbus()) != (0 == i->mixbus ())) { + if (route && (0 == route->mixbus()) != (0 == r->mixbus ())) { continue; } #endif - if (i->soloed ()) { - routes_on->push_back (i); + if (r->soloed ()) { + routes_on->push_back (r); } else if (smr) { - routes_off->push_back (i); + routes_off->push_back (r); } } if (exclusive) { - set_controls (route_list_to_control_list (routes_on, &Stripable::solo_control), false, Controllable::UseGroup); + set_controls (stripable_list_to_control_list (routes_on, &Stripable::solo_control), false, Controllable::UseGroup); } if (smr) { diff --git a/libs/ardour/solo_mute_release.cc b/libs/ardour/solo_mute_release.cc index 0c8dd9cede..e6c5876966 100644 --- a/libs/ardour/solo_mute_release.cc +++ b/libs/ardour/solo_mute_release.cc @@ -40,20 +40,20 @@ SoloMuteRelease::set_exclusive (bool e) } void -SoloMuteRelease::set (std::shared_ptr r) +SoloMuteRelease::set (std::shared_ptr r) { - std::shared_ptr rl (new RouteList); + std::shared_ptr sl (new StripableList); if (active) { - rl->push_back (r); - routes_on = rl; + sl->push_back (r); + routes_on = sl; } else { - rl->push_back (r); - routes_off = rl; + sl->push_back (r); + routes_off = sl; } } void -SoloMuteRelease::set (std::shared_ptr rl) +SoloMuteRelease::set (std::shared_ptr rl) { if (active) { routes_on = rl; @@ -63,7 +63,7 @@ SoloMuteRelease::set (std::shared_ptr rl) } void -SoloMuteRelease::set (std::shared_ptr on, std::shared_ptr off) +SoloMuteRelease::set (std::shared_ptr on, std::shared_ptr off) { routes_on = on; routes_off = off; @@ -79,11 +79,11 @@ void SoloMuteRelease::release (Session* s, bool mute) const { if (mute) { - s->set_controls (route_list_to_control_list (routes_off, &Stripable::mute_control), 0.0, exclusive ? Controllable::NoGroup : Controllable::UseGroup); - s->set_controls (route_list_to_control_list (routes_on, &Stripable::mute_control), 1.0, exclusive ? Controllable::NoGroup : Controllable::UseGroup); + s->set_controls (stripable_list_to_control_list (routes_off, &Stripable::mute_control), 0.0, exclusive ? Controllable::NoGroup : Controllable::NoGroup); + s->set_controls (stripable_list_to_control_list (routes_on, &Stripable::mute_control), 1.0, exclusive ? Controllable::NoGroup : Controllable::NoGroup); } else { - s->set_controls (route_list_to_control_list (routes_off, &Stripable::solo_control), 0.0, exclusive ? Controllable::NoGroup : Controllable::UseGroup); - s->set_controls (route_list_to_control_list (routes_on, &Stripable::solo_control), 1.0, exclusive ? Controllable::NoGroup : Controllable::UseGroup); + s->set_controls (stripable_list_to_control_list (routes_off, &Stripable::solo_control), 0.0, exclusive ? Controllable::NoGroup : Controllable::NoGroup); + s->set_controls (stripable_list_to_control_list (routes_on, &Stripable::solo_control), 1.0, exclusive ? Controllable::NoGroup : Controllable::NoGroup); if (port_monitors && s->monitor_out ()) { s->engine().monitor_port().set_active_monitors (*port_monitors);