Implement additional ControlList interpolation methods.
[ardour.git] / libs / ardour / session_state.cc
index 4ad1f91f4ab716fdcfbba31ce189c3d27ee7be29..a908502bd0d3593f95d9ef395a9cea009f34d4eb 100644 (file)
 #include "ardour/revision.h"
 #include "ardour/route_group.h"
 #include "ardour/send.h"
+#include "ardour/selection.h"
 #include "ardour/session.h"
 #include "ardour/session_directory.h"
 #include "ardour/session_metadata.h"
@@ -1126,6 +1127,17 @@ Session::export_track_state (boost::shared_ptr<RouteList> rl, const string& path
        return tree.write (sn.c_str());
 }
 
+namespace
+{
+struct route_id_compare {
+       bool
+       operator() (const boost::shared_ptr<Route>& r1, const boost::shared_ptr<Route>& r2)
+       {
+               return r1->id () < r2->id ();
+       }
+};
+} // anon namespace
+
 XMLNode&
 Session::state (bool full_state)
 {
@@ -1176,10 +1188,9 @@ Session::state (bool full_state)
                        child = node->add_child ("Path");
                        child->add_content (p);
                }
+               node->set_property ("end-is-free", _session_range_end_is_free);
        }
 
-       node->set_property ("end-is-free", _session_range_end_is_free);
-
        /* save the ID counter */
 
        node->set_property ("id-counter", ID::counter());
@@ -1276,6 +1287,8 @@ Session::state (bool full_state)
 
        if (full_state) {
 
+               node->add_child_nocopy (_selection->get_state());
+
                if (_locations) {
                        node->add_child_nocopy (_locations->get_state());
                }
@@ -1326,17 +1339,11 @@ Session::state (bool full_state)
        {
                boost::shared_ptr<RouteList> r = routes.reader ();
 
-               RoutePublicOrderSorter cmp;
-               RouteList public_order (*r);
-               public_order.sort (cmp);
-
-               /* the sort should have put the monitor out first */
-
-               if (_monitor_out) {
-                       assert (_monitor_out == public_order.front());
-               }
+               route_id_compare cmp;
+               RouteList xml_node_order (*r);
+               xml_node_order.sort (cmp);
 
-               for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
+               for (RouteList::const_iterator i = xml_node_order.begin(); i != xml_node_order.end(); ++i) {
                        if (!(*i)->is_auditioner()) {
                                if (full_state) {
                                        child->add_child_nocopy ((*i)->get_state());
@@ -1645,6 +1652,10 @@ Session::set_state (const XMLNode& node, int version)
                }
        }
 
+       if ((child = find_named_node (node, X_("Selection")))) {
+               _selection->set_state (*child, version);
+       }
+
        update_route_record_state ();
 
        /* here beginneth the second phase ... */
@@ -3579,6 +3590,12 @@ Session::controllable_by_id (const PBD::ID& id)
        return boost::shared_ptr<Controllable>();
 }
 
+boost::shared_ptr<AutomationControl>
+Session::automation_control_by_id (const PBD::ID& id)
+{
+       return boost::dynamic_pointer_cast<AutomationControl> (controllable_by_id (id));
+}
+
 boost::shared_ptr<Controllable>
 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
 {
@@ -3823,13 +3840,21 @@ Session::restore_history (string snapshot_name)
 
                XMLNode *t = *it;
                UndoTransaction* ut = new UndoTransaction ();
-               struct timeval tv;
 
-               ut->set_name(t->property("name")->value());
-               stringstream ss(t->property("tv-sec")->value());
-               ss >> tv.tv_sec;
-               ss.str(t->property("tv-usec")->value());
-               ss >> tv.tv_usec;
+               std::string name;
+               int64_t tv_sec;
+               int64_t tv_usec;
+
+               if (!t->get_property ("name", name) || !t->get_property ("tv-sec", tv_sec) ||
+                   !t->get_property ("tv-usec", tv_usec)) {
+                       continue;
+               }
+
+               ut->set_name (name);
+
+               struct timeval tv;
+               tv.tv_sec = tv_sec;
+               tv.tv_usec = tv_usec;
                ut->set_timestamp(tv);
 
                for (XMLNodeConstIterator child_it  = t->children().begin();
@@ -5018,6 +5043,8 @@ Session::save_as (SaveAs& saveas)
                        session_dirs.push_back (sp);
                        refresh_disk_space ();
 
+                       _writable = exists_and_writable (_path);
+
                        /* ensure that all existing tracks reset their current capture source paths
                         */
                        reset_write_sources (true, true);