Add support for newly introduced class ARDOUR::DSPLoadCalculator (when building with...
[ardour.git] / libs / ardour / session_state.cc
index 266096a8942e9396f6ad03654c714b19eef18db5..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"
 #include "ardour/playlist_source.h"
 #include "ardour/port.h"
 #include "ardour/processor.h"
+#include "ardour/profile.h"
 #include "ardour/proxy_controllable.h"
 #include "ardour/recent_sessions.h"
 #include "ardour/region_factory.h"
@@ -128,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)
 {
@@ -141,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.
@@ -270,6 +284,7 @@ Session::post_engine_init ()
                
                Config->map_parameters (ff);
                config.map_parameters (ft);
+                _butler->map_parameters ();
 
                /* Reset all panners */
                
@@ -351,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
 {
@@ -490,7 +540,7 @@ Session::create (const string& session_template, BusProfile* bus_profile)
        _writable = exists_and_writable (_path);
 
        if (!session_template.empty()) {
-               std::string in_path = session_template_dir_to_file (session_template);
+               std::string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
 
                ifstream in(in_path.c_str());
 
@@ -506,10 +556,12 @@ Session::create (const string& session_template, BusProfile* bus_profile)
                                out << in.rdbuf();
                                 _is_new = false;
 
-                               /* Copy plugin state files from template to new session */
-                               std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
-                               copy_recurse (template_plugins, plugins_dir ());
-                               
+                                if (!ARDOUR::Profile->get_trx()) {
+                                       /* Copy plugin state files from template to new session */
+                                       std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
+                                       copy_recurse (template_plugins, plugins_dir ());
+                                }
+                                
                                return 0;
 
                        } else {
@@ -526,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;
 
@@ -537,8 +603,9 @@ Session::create (const string& session_template, BusProfile* bus_profile)
                RouteList rl;
                 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
 
-               if (bus_profile->master_out_channels) {
-                       boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
+                // Waves Tracks: always create master bus for Tracks
+                if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
+                       boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
                         if (r->init ()) {
                                 return -1;
                         }
@@ -562,16 +629,20 @@ Session::create (const string& session_template, BusProfile* bus_profile)
                        add_routes (rl, false, false, false);
                }
 
-                /* this allows the user to override settings with an environment variable.
-                 */
-
-                if (no_auto_connect()) {
-                        bus_profile->input_ac = AutoConnectOption (0);
-                        bus_profile->output_ac = AutoConnectOption (0);
-                }
-
-                Config->set_input_auto_connect (bus_profile->input_ac);
-                Config->set_output_auto_connect (bus_profile->output_ac);
+               // Waves Tracks: Skip this. Always use autoconnection for Tracks
+               if (!ARDOUR::Profile->get_trx()) {
+                       
+                       /* this allows the user to override settings with an environment variable.
+                        */
+                       
+                       if (no_auto_connect()) {
+                               bus_profile->input_ac = AutoConnectOption (0);
+                               bus_profile->output_ac = AutoConnectOption (0);
+                       }
+                       
+                       Config->set_input_auto_connect (bus_profile->input_ac);
+                       Config->set_output_auto_connect (bus_profile->output_ac);
+               }
         }
 
        if (Config->get_use_monitor_bus() && bus_profile) {
@@ -1063,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 ());
@@ -1349,7 +1421,7 @@ Session::set_state (const XMLNode& node, int version)
                ControlProtocolManager::instance().set_state (*child, version);
        }
 
-       update_have_rec_enabled_track ();
+       update_route_record_state ();
 
        /* here beginneth the second phase ... */
 
@@ -1870,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
@@ -2022,24 +2092,31 @@ Session::save_template (string template_name)
                template_dir_path = template_name;
        }
 
-       if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
-               warning << string_compose(_("Template \"%1\" already exists - new version not created"),
-                               template_dir_path) << endmsg;
-               return -1;
-       }
-       
-       if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
-               error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
-                               template_dir_path, g_strerror (errno)) << endmsg;
-               return -1;
+       if (!ARDOUR::Profile->get_trx()) {
+               if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
+                       warning << string_compose(_("Template \"%1\" already exists - new version not created"),
+                                                                         template_dir_path) << endmsg;
+                       return -1;
+               }
+               
+               if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
+                       error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
+                                                                       template_dir_path, g_strerror (errno)) << endmsg;
+                       return -1;
+               }
        }
 
        /* file to write */
        std::string template_file_path;
-       if (absolute_path) {
-               template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
+       
+       if (ARDOUR::Profile->get_trx()) {
+               template_file_path = template_name;
        } else {
-               template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
+               if (absolute_path) {
+                       template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
+               } else {
+                       template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
+               }
        }
 
        SessionSaveUnderway (); /* EMIT SIGNAL */
@@ -2052,17 +2129,20 @@ Session::save_template (string template_name)
                return -1;
        }
 
-       /* copy plugin state directory */
+       if (!ARDOUR::Profile->get_trx()) {
+               /* copy plugin state directory */
 
-       std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
+               std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
 
-       if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
-               error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
-                               template_plugin_state_path, g_strerror (errno)) << endmsg;
-               return -1;
+               if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
+                       error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
+                                                                       template_plugin_state_path, g_strerror (errno)) << endmsg;
+                       return -1;
+               }
+               copy_files (plugins_dir(), template_plugin_state_path);
        }
 
-       copy_recurse (plugins_dir(), template_plugin_state_path);
+       store_recent_templates (template_file_path);
 
        return 0;
 }
@@ -2265,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
@@ -2449,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)
 {
@@ -2468,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);
@@ -2481,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;
@@ -2497,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;
@@ -2812,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);
                                }
                        }
                }
@@ -2931,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) {
@@ -3585,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 ();
@@ -4176,7 +4294,15 @@ Session::save_as (SaveAs& saveas)
 
                                std::string from = *i;
 
-                               if ((*i).find (audiofile_dir_string) != string::npos) {
+#ifdef __APPLE__
+                               string filename = Glib::path_get_basename (from);
+                               std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
+                               if (filename == ".DS_STORE") {
+                                       continue;
+                               }
+#endif
+                               
+                               if (from.find (audiofile_dir_string) != string::npos) {
                                        
                                        /* audio file: only copy if asked */
 
@@ -4187,7 +4313,8 @@ Session::save_as (SaveAs& saveas)
                                                info << "media file copying from " << from << " to " << to << endmsg;
                                                
                                                if (!copy_file (from, to)) {
-                                                       throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
+                                                       throw Glib::FileError (Glib::FileError::IO_ERROR,
+                                                                                                  string_compose(_("\ncopying \"%1\" failed !"), from));
                                                }
                                        }
                                        
@@ -4195,7 +4322,7 @@ Session::save_as (SaveAs& saveas)
                                        
                                        internal_file_cnt++;
 
-                               } else if ((*i).find (midifile_dir_string) != string::npos) {
+                               } else if (from.find (midifile_dir_string) != string::npos) {
 
                                        /* midi file: always copy unless
                                         * creating an empty new session
@@ -4216,7 +4343,7 @@ Session::save_as (SaveAs& saveas)
                                                
                                        internal_file_cnt++;
                                        
-                               } else if ((*i).find (analysis_dir_string) != string::npos) {
+                               } else if (from.find (analysis_dir_string) != string::npos) {
 
                                        /*  make sure analysis dir exists in
                                         *  new session folder, but we're not
@@ -4235,14 +4362,14 @@ Session::save_as (SaveAs& saveas)
                                        bool do_copy = true;
                                        
                                        for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
-                                               if (((*i).length() > (*v).length()) && ((*i).find (*v) == (*i).length() - (*v).length())) {
+                                               if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
                                                        /* end of filename matches extension, do not copy file */
                                                        do_copy = false;
                                                        break;
                                                } 
                                        }
 
-                                       if (!saveas.copy_media && (*i).find (peakfile_suffix) != string::npos) {
+                                       if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
                                                /* don't copy peakfiles if
                                                 * we're not copying media
                                                 */
@@ -4250,7 +4377,7 @@ Session::save_as (SaveAs& saveas)
                                        }
                                        
                                        if (do_copy) {
-                                               string to = Glib::build_filename (to_dir, (*i).substr (prefix_len));
+                                               string to = Glib::build_filename (to_dir, from.substr (prefix_len));
                                                
                                                info << "attempting to make directory/folder " << to << endmsg;
 
@@ -4261,7 +4388,8 @@ Session::save_as (SaveAs& saveas)
                                                info << "attempting to copy " << from << " to " << to << endmsg;
                                                
                                                if (!copy_file (from, to)) {
-                                                       throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
+                                                       throw Glib::FileError (Glib::FileError::IO_ERROR,
+                                                                                                  string_compose(_("\ncopying \"%1\" failed !"), from));
                                                }
                                        }
                                }
@@ -4272,7 +4400,7 @@ Session::save_as (SaveAs& saveas)
                                */
                                
                                GStatBuf gsb;
-                               g_stat ((*i).c_str(), &gsb);
+                               g_stat (from.c_str(), &gsb);
                                copied += gsb.st_size;
                                cnt++;
                                
@@ -4367,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
@@ -4388,6 +4517,8 @@ Session::save_as (SaveAs& saveas)
                }
 
                saveas.final_session_folder_name = _path;
+
+               store_recent_sessions (_name, _path);
                
                if (!saveas.switch_to) {