Wouldn't it be nice if plugin presets had a description/comment?
[ardour.git] / libs / ardour / route_graph.cc
index ee02afef2401710aaca5a8987a612d98e1386c06..dfe61c4c331b378026ff5dc72efa752e095fa2d8 100644 (file)
@@ -20,8 +20,9 @@
 
 #include "ardour/route.h"
 #include "ardour/route_graph.h"
+#include "ardour/track.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
@@ -59,6 +60,24 @@ GraphEdges::find_in_from_to_with_sends (GraphVertex from, GraphVertex to)
        return _from_to_with_sends.end ();
 }
 
+GraphEdges::EdgeMapWithSends::iterator
+GraphEdges::find_recursively_in_from_to_with_sends (GraphVertex from, GraphVertex to)
+{
+       typedef EdgeMapWithSends::iterator Iter;
+       pair<Iter, Iter> r = _from_to_with_sends.equal_range (from);
+       for (Iter i = r.first; i != r.second; ++i) {
+               if (i->second.first == to) {
+                       return i;
+               }
+               GraphEdges::EdgeMapWithSends::iterator t = find_recursively_in_from_to_with_sends (i->second.first, to);
+               if (t != _from_to_with_sends.end ()) {
+                       return t;
+               }
+       }
+
+       return _from_to_with_sends.end ();
+}
+
 /** @param via_sends_only if non-0, filled in with true if the edge is a
  *  path via a send only.
  *  @return true if the given edge is present.
@@ -70,7 +89,7 @@ GraphEdges::has (GraphVertex from, GraphVertex to, bool* via_sends_only)
        if (i == _from_to_with_sends.end ()) {
                return false;
        }
-       
+
        if (via_sends_only) {
                *via_sends_only = i->second.second;
        }
@@ -78,6 +97,16 @@ GraphEdges::has (GraphVertex from, GraphVertex to, bool* via_sends_only)
        return true;
 }
 
+bool
+GraphEdges::feeds (GraphVertex from, GraphVertex to)
+{
+       EdgeMapWithSends::iterator i = find_recursively_in_from_to_with_sends (from, to);
+       if (i == _from_to_with_sends.end ()) {
+               return false;
+       }
+       return true;
+}
+
 /** @return the vertices that are fed from `r' */
 set<GraphVertex>
 GraphEdges::from (GraphVertex r) const
@@ -86,7 +115,7 @@ GraphEdges::from (GraphVertex r) const
        if (i == _from_to.end ()) {
                return set<GraphVertex> ();
        }
-       
+
        return i->second;
 }
 
@@ -99,7 +128,7 @@ GraphEdges::remove (GraphVertex from, GraphVertex to)
        if (i->second.empty ()) {
                _from_to.erase (i);
        }
-       
+
        EdgeMap::iterator j = _to_from.find (to);
        assert (j != _to_from.end ());
        j->second.erase (from);
@@ -139,7 +168,7 @@ GraphEdges::dump () const
                }
                cout << "\n";
        }
-       
+
        for (EdgeMap::const_iterator i = _to_from.begin(); i != _to_from.end(); ++i) {
                cout << "TO: " << i->first->name() << " ";
                for (set<GraphVertex>::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
@@ -167,21 +196,41 @@ struct RouteRecEnabledComparator
 {
        bool operator () (GraphVertex r1, GraphVertex r2) const
        {
-               if (r1->record_enabled()) {
-                       if (r2->record_enabled()) {
+               boost::shared_ptr<Track> t1 (boost::dynamic_pointer_cast<Track>(r1));
+               boost::shared_ptr<Track> t2 (boost::dynamic_pointer_cast<Track>(r2));
+               PresentationInfo::order_t r1o = r1->presentation_info().order();
+               PresentationInfo::order_t r2o = r2->presentation_info().order();
+
+               if (!t1) {
+                       if (!t2) {
+                               /* makes no difference which is first, use presentation order */
+                               return r1o < r2o;
+                       } else {
+                               /* r1 is not a track, r2 is, run it early */
+                               return false;
+                       }
+               }
+
+               if (!t2) {
+                       /* we already tested !t1, so just use presentation order */
+                       return r1o < r2o;
+               }
+
+               if (t1->rec_enable_control()->get_value()) {
+                       if (t2->rec_enable_control()->get_value()) {
                                /* both rec-enabled, just use signal order */
-                               return r1->order_key () < r2->order_key ();
+                               return r1o < r2o;
                        } else {
-                               /* r1 rec-enabled, r2 not rec-enabled, run r2 early */
+                               /* t1 rec-enabled, t2 not rec-enabled, run t2 early */
                                return false;
                        }
                } else {
-                       if (r2->record_enabled()) {
-                               /* r2 rec-enabled, r1 not rec-enabled, run r1 early */
+                       if (t2->rec_enable_control()->get_value()) {
+                               /* t2 rec-enabled, t1 not rec-enabled, run t1 early */
                                return true;
                        } else {
-                               /* neither rec-enabled, use signal order */
-                               return r1->order_key () < r2->order_key ();
+                               /* neither rec-enabled, use presentation order */
+                               return r1o < r2o;
                        }
                }
        }
@@ -197,7 +246,7 @@ ARDOUR::topological_sort (
        )
 {
        boost::shared_ptr<RouteList> sorted_routes (new RouteList);
-       
+
        /* queue of routes to process */
        RouteList queue;
 
@@ -217,7 +266,7 @@ ARDOUR::topological_sort (
        /* Do the sort: algorithm is Kahn's from Wikipedia.
           `Topological sorting of large networks', Communications of the ACM 5(11):558-562.
        */
-       
+
        while (!queue.empty ()) {
                GraphVertex r = queue.front ();
                queue.pop_front ();