diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 35dd06d615..acfdf9c1f5 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -744,6 +744,9 @@ private: bool input_port_count_changing (ChanCount); bool output_port_count_changing (ChanCount); + bool output_effectively_connected_real () const; + mutable std::map _connection_cache; + int configure_processors_unlocked (ProcessorStreams*, Glib::Threads::RWLock::WriterLock*); bool set_meter_point_unlocked (); void apply_processor_order (const ProcessorList& new_order); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 351d2d3d39..adeb77f729 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -3674,6 +3674,13 @@ Route::feeds_according_to_graph (boost::shared_ptr other) bool Route::output_effectively_connected () const +{ + _connection_cache.clear (); + return output_effectively_connected_real (); +} + +bool +Route::output_effectively_connected_real () const { if (!_output->connected ()) { return false; @@ -3687,15 +3694,29 @@ Route::output_effectively_connected () const return true; } + /* now follow connections downstream */ boost::shared_ptr routes = _session.get_routes (); for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { - if ((*i).get() == this) { + Route* rp = (*i).get(); + if (rp == this) { continue; } - if ((*i)->input()->connected_to (_output)) { - if ((*i)->output_effectively_connected ()) { - return true; - } + if (!(*i)->input()->connected_to (_output)) { + continue; + } + if (_connection_cache.find (rp) != _connection_cache.end ()) { + return _connection_cache[rp]; + } + /* First mark node a traversed to prevent endless recursion. + * Othewise graph loops A -> B -> A will cause a stack overflow. + */ + _connection_cache[rp] = false; + + /* recurse downstream, check connected route */ + bool rv = (*i)->output_effectively_connected_real (); + _connection_cache[rp] = rv; + if (rv) { + return true; } } return false;