Add support for newly introduced class ARDOUR::DSPLoadCalculator (when building with...
[ardour.git] / libs / ardour / session_state.cc
index 267eaa092869d8fe24ad225070ce8a5c25601da7..bb4a8265ef393e9182d5b1c16aa439f00a533ac3 100644 (file)
@@ -66,6 +66,7 @@
 #include "pbd/boost_debug.h"
 #include "pbd/basename.h"
 #include "pbd/controllable_descriptor.h"
+#include "pbd/debug.h"
 #include "pbd/enumwriter.h"
 #include "pbd/error.h"
 #include "pbd/file_utils.h"
@@ -129,6 +130,8 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
+#define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
+
 void
 Session::pre_engine_init (string fullpath)
 {
@@ -142,8 +145,18 @@ Session::pre_engine_init (string fullpath)
        _path = canonical_path(fullpath);
 
        /* is it new ? */
+       if (Profile->get_trx() ) {
+               // Waves TracksLive has a usecase of session replacement with a new one.
+               // We should check session state file (<session_name>.ardour) existance
+               // to determine if the session is new or not
 
-       _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
+               string full_session_name = Glib::build_filename( fullpath, _name );
+               full_session_name += statefile_suffix;
+               
+               _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
+       } else {
+               _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
+       }
 
        /* finish initialization that can't be done in a normal C++ constructor
           definition.
@@ -271,6 +284,7 @@ Session::post_engine_init ()
                
                Config->map_parameters (ff);
                config.map_parameters (ft);
+                _butler->map_parameters ();
 
                /* Reset all panners */
                
@@ -352,9 +366,44 @@ Session::post_engine_init ()
                state_was_pending = false;
        }
 
+       /* Now, finally, we can fill the playback buffers */
+    
+       BootMessage (_("Filling playback buffers"));
+    
+       boost::shared_ptr<RouteList> rl = routes.reader();
+       for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
+               boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
+               if (trk && !trk->hidden()) {
+                       trk->seek (_transport_frame, true);
+               }
+       }
+
        return 0;
 }
 
+void
+Session::session_loaded ()
+{
+       SessionLoaded();
+       
+       _state_of_the_state = Clean;
+       
+       DirtyChanged (); /* EMIT SIGNAL */
+       
+       if (_is_new) {
+               save_state ("");
+       } else if (state_was_pending) {
+               save_state ("");
+               remove_pending_capture_state ();
+               state_was_pending = false;
+       }
+       
+       /* Now, finally, we can fill the playback buffers */
+       
+       BootMessage (_("Filling playback buffers"));
+       force_locate (_transport_frame, false);
+}
+
 string
 Session::raid_path () const
 {
@@ -529,7 +578,21 @@ Session::create (const string& session_template, BusProfile* bus_profile)
 
        }
 
-       /* set initial start + end point */
+       if (Profile->get_trx()) {
+       
+               /* set initial start + end point : ARDOUR::Session::session_end_shift long.
+                  Remember that this is a brand new session. Sessions
+                  loaded from saved state will get this range from the saved state.
+               */
+               
+               set_session_range_location (0, 0);
+               
+               /* Initial loop location, from absolute zero, length 10 seconds  */
+               
+               Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"),  Location::IsAutoLoop);
+               _locations->add (loc, true);
+               set_auto_loop_location (loc);
+       }
 
        _state_of_the_state = Clean;
 
@@ -1071,6 +1134,7 @@ Session::state (bool full_state)
                XMLNode& locations_state = loc.get_state();
                
                if (ARDOUR::Profile->get_trx() && _locations) {
+                       // For tracks we need stored the Auto Loop Range and all MIDI markers.
                        for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
                                if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
                                        locations_state.add_child_nocopy ((*i)->get_state ());
@@ -1878,17 +1942,15 @@ Session::get_sources_as_xml ()
 void
 Session::reset_write_sources (bool mark_write_complete, bool force)
 {
-    boost::shared_ptr<RouteList> rl = routes.reader();
-    for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
-        boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
-        if (tr) {
-                       
-                       // block state saving
+       boost::shared_ptr<RouteList> rl = routes.reader();
+       for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+               boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
+               if (tr) {
                        _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
                        tr->reset_write_sources(mark_write_complete, force);
                        _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
-        }
-    }
+               }
+       }
 }
 
 int
@@ -2283,25 +2345,25 @@ Session::get_best_session_directory_for_new_audio ()
 string
 Session::automation_dir () const
 {
-       return Glib::build_filename (_path, "automation");
+       return Glib::build_filename (_path, automation_dir_name);
 }
 
 string
 Session::analysis_dir () const
 {
-       return Glib::build_filename (_path, "analysis");
+       return Glib::build_filename (_path, analysis_dir_name);
 }
 
 string
 Session::plugins_dir () const
 {
-       return Glib::build_filename (_path, "plugins");
+       return Glib::build_filename (_path, plugins_dir_name);
 }
 
 string
 Session::externals_dir () const
 {
-       return Glib::build_filename (_path, "externals");
+       return Glib::build_filename (_path, externals_dir_name);
 }
 
 int
@@ -2467,6 +2529,16 @@ Session::add_commands (vector<Command*> const & cmds)
        }
 }
 
+void
+Session::add_command (Command* const cmd)
+{
+       assert (_current_trans);
+       DEBUG_UNDO_HISTORY (
+           string_compose ("Current Undo Transaction %1, adding command: %2",
+                           _current_trans->name (),
+                           cmd->name ()));
+       _current_trans->add_command (cmd);
+}
 void
 Session::begin_reversible_command (const string& name)
 {
@@ -2486,10 +2558,17 @@ Session::begin_reversible_command (GQuark q)
        */
 
        if (_current_trans == 0) {
+               DEBUG_UNDO_HISTORY (string_compose (
+                   "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
+
                /* start a new transaction */
                assert (_current_trans_quarks.empty ());
                _current_trans = new UndoTransaction();
                _current_trans->set_name (g_quark_to_string (q));
+       } else {
+               DEBUG_UNDO_HISTORY (
+                   string_compose ("Begin Reversible Command, current transaction: %1",
+                                   _current_trans->name ()));
        }
 
        _current_trans_quarks.push_front (q);
@@ -2499,6 +2578,8 @@ void
 Session::abort_reversible_command ()
 {
        if (_current_trans != 0) {
+               DEBUG_UNDO_HISTORY (
+                   string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
                _current_trans->clear();
                delete _current_trans;
                _current_trans = 0;
@@ -2515,18 +2596,34 @@ Session::commit_reversible_command (Command *cmd)
        struct timeval now;
 
        if (cmd) {
+               DEBUG_UNDO_HISTORY (
+                   string_compose ("Current Undo Transaction %1, adding command: %2",
+                                   _current_trans->name (),
+                                   cmd->name ()));
                _current_trans->add_command (cmd);
        }
 
+       DEBUG_UNDO_HISTORY (
+           string_compose ("Commit Reversible Command, current transaction: %1",
+                           _current_trans->name ()));
+
        _current_trans_quarks.pop_front ();
 
        if (!_current_trans_quarks.empty ()) {
+               DEBUG_UNDO_HISTORY (
+                   string_compose ("Commit Reversible Command, transaction is not "
+                                   "top-level, current transaction: %1",
+                                   _current_trans->name ()));
                /* the transaction we're committing is not the top-level one */
                return;
        }
 
        if (_current_trans->empty()) {
                /* no commands were added to the transaction, so just get rid of it */
+               DEBUG_UNDO_HISTORY (
+                   string_compose ("Commit Reversible Command, No commands were "
+                                   "added to current transaction: %1",
+                                   _current_trans->name ()));
                delete _current_trans;
                _current_trans = 0;
                return;
@@ -2830,17 +2927,18 @@ Session::cleanup_sources (CleanupReport& rep)
                                        */
                                        
                                        RegionFactory::remove_regions_using_source (i->second);
-                                       sources.erase (i);
                                        
                                        // also remove source from all_sources
                                        
                                        for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
                                                spath = Glib::path_get_basename (*j);
-                                               if ( spath == i->second->name () ) {
+                                               if (spath == i->second->name()) {
                                                        all_sources.erase (j);
                                                        break;
                                                }
                                        }
+
+                                       sources.erase (i);
                                }
                        }
                }
@@ -2949,12 +3047,12 @@ Session::cleanup_sources (CleanupReport& rep)
                /* see if there an easy to find peakfile for this file, and remove it.
                 */
 
-                string base = basename_nosuffix (*x);
+                string base = Glib::path_get_basename (*x);
                 base += "%A"; /* this is what we add for the channel suffix of all native files,
                                  or for the first channel of embedded files. it will miss
                                  some peakfiles for other channels
                               */
-               string peakpath = peak_path (base);
+               string peakpath = construct_peak_filepath (base);
 
                if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
                        if (::g_unlink (peakpath.c_str()) != 0) {
@@ -3603,6 +3701,8 @@ Session::config_changed (std::string p, bool ours)
                reconnect_ltc_output ();
        } else if (p == "timecode-generator-offset") {
                ltc_tx_parse_offset();
+       } else if (p == "auto-return-target-list") {
+               follow_playhead_priority ();
        }
 
        set_dirty ();
@@ -4395,6 +4495,7 @@ Session::save_as (SaveAs& saveas)
                        if (internal_file_cnt) {
                                for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
                                        ensure_search_path_includes (*s, DataType::AUDIO);
+                                       cerr << "be sure to include " << *s << "  for audio" << endl;
                                }
 
                                /* we do not do this for MIDI because we copy