Merge branch 'master' into saveas
[ardour.git] / libs / ardour / session_state.cc
index df2b919c161e834d30e72f37b02696c5fe215414..3ab6ff09b579fc0089188981bc79c7eb004bb4c8 100644 (file)
@@ -232,6 +232,7 @@ Session::post_engine_init ()
        try {
                /* tempo map requires sample rate knowledge */
 
+               delete _tempo_map;
                _tempo_map = new TempoMap (_current_frame_rate);
                _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
                
@@ -693,7 +694,7 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot
                }
        }
 
-       SaveSession (); /* EMIT SIGNAL */
+       SessionSaveUnderway (); /* EMIT SIGNAL */
 
        tree.set_root (&get_state());
 
@@ -877,7 +878,7 @@ Session::load_state (string snapshot_name)
 int
 Session::load_options (const XMLNode& node)
 {
-       LocaleGuard lg (X_("POSIX"));
+       LocaleGuard lg (X_("C"));
        config.set_variables (node);
        return 0;
 }
@@ -1376,8 +1377,12 @@ Session::load_routes (const XMLNode& node, int version)
                new_routes.push_back (route);
        }
 
+       BootMessage (_("Tracks/busses loaded;  Adding to Session"));
+
        add_routes (new_routes, false, false, false);
 
+       BootMessage (_("Finished adding tracks/busses"));
+
        return 0;
 }
 
@@ -1844,6 +1849,22 @@ Session::get_sources_as_xml ()
        return *node;
 }
 
+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
+                       _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
 Session::load_sources (const XMLNode& node)
 {
@@ -2064,7 +2085,7 @@ Session::refresh_disk_space ()
                        _total_free_4k_blocks_uncertain = true;
                }
        }
-#elif defined (COMPILER_MSVC)
+#elif defined PLATFORM_WINDOWS
        vector<string> scanned_volumes;
        vector<string>::iterator j;
        vector<space_and_path>::iterator i;
@@ -2428,6 +2449,17 @@ Session::begin_reversible_command (GQuark q)
        _current_trans_quarks.push_front (q);
 }
 
+void
+Session::abort_reversible_command ()
+{
+       if (_current_trans != 0) {
+               _current_trans->clear();
+               delete _current_trans;
+               _current_trans = 0;
+               _current_trans_quarks.clear();
+       }
+}
+
 void
 Session::commit_reversible_command (Command *cmd)
 {
@@ -3605,6 +3637,17 @@ Session::rename (const std::string& new_name, bool after_copy)
 
        string const old_sources_root = _session_dir->sources_root();
 
+       if (!_writable || (_state_of_the_state & CannotSave)) {
+               error << _("Cannot rename read-only session.") << endmsg;
+               return 0; // don't show "messed up" warning
+       }
+        if (record_status() == Recording) {
+               error << _("Cannot rename session while recording") << endmsg;
+               return 0; // don't show "messed up" warning
+       }
+
+       StateProtector stp (this);
+
        /* Rename:
 
         * session directory
@@ -3620,6 +3663,7 @@ Session::rename (const std::string& new_name, bool after_copy)
         */
 
        if (!after_copy) {
+
                for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
                        
                        if (first) {
@@ -3655,6 +3699,7 @@ Session::rename (const std::string& new_name, bool after_copy)
        first = false;
        
        for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
+
                vector<string> v;
 
                oldstr = (*i).path;
@@ -3686,7 +3731,8 @@ Session::rename (const std::string& new_name, bool after_copy)
                /* Reset path in "session dirs" */
                
                (*i).path = newstr;
-
+               (*i).blocks = 0;
+               
                /* reset primary SessionDirectory object */
                
                if (first) {
@@ -3701,7 +3747,7 @@ Session::rename (const std::string& new_name, bool after_copy)
                string new_interchange_dir;
 
                /* use newstr here because we renamed the path that used to be oldstr to newstr above */                
-
+               
                v.push_back (newstr); 
                v.push_back (interchange_dir_name);
                v.push_back (Glib::path_get_basename (oldstr));
@@ -3734,7 +3780,7 @@ Session::rename (const std::string& new_name, bool after_copy)
        cerr << "Rename " << oldstr << " => " << newstr << endl;                
 
        if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
-               error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
+               error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
                return 1;
        }
 
@@ -3748,7 +3794,7 @@ Session::rename (const std::string& new_name, bool after_copy)
                cerr << "Rename " << oldstr << " => " << newstr << endl;                
                
                if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
-                       error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
+                       error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
                        return 1;
                }
        }
@@ -3757,6 +3803,18 @@ Session::rename (const std::string& new_name, bool after_copy)
                /* remove old name from recent sessions */
                remove_recent_sessions (_path);
                _path = new_path;
+
+               /* update file source paths */
+               
+               for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
+                       boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
+                       if (fs) {
+                               string p = fs->path ();
+                               boost::replace_all (p, old_sources_root, _session_dir->sources_root());
+                               fs->set_path (p);
+                               SourceFactory::setup_peakfile(i->second, true);
+                       }
+               }
        }
 
        _current_snapshot_name = new_name;
@@ -3867,7 +3925,6 @@ Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,
                        }
                        
                        if (fs->within_session()) {
-                               cerr << "skip " << fs->name() << endl;
                                continue;
                        }
                        
@@ -3902,9 +3959,14 @@ Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,
                                break;
                                
                        case DataType::MIDI:
+                               /* XXX not implemented yet */
                                break;
                        }
                        
+                       if (new_path.empty()) {
+                               continue;
+                       }
+                       
                        cerr << "Move " << old_path << " => " << new_path << endl;
                        
                        if (!copy_file (old_path, new_path)) {
@@ -3942,6 +4004,22 @@ Session::save_as_bring_callback (uint32_t,uint32_t,string)
        */
 }
 
+static string
+make_new_media_path (string old_path, string new_session_folder, string new_session_path)
+{
+       /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
+
+       string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
+       vector<string> v;
+       v.push_back (new_session_folder); /* full path */
+       v.push_back (interchange_dir_name);
+       v.push_back (new_session_path);   /* just one directory/folder */
+       v.push_back (typedir);
+       v.push_back (Glib::path_get_basename (old_path));
+       
+       return Glib::build_filename (v);
+}
+
 int
 Session::save_as (SaveAs& saveas)
 {
@@ -4044,18 +4122,8 @@ Session::save_as (SaveAs& saveas)
 
                                        if (saveas.copy_media) {
                                                
-                                               /* typedir is the "midifiles" or "audiofiles" etc. part of the path.
-                                                */
-                                               string typedir = Glib::path_get_basename (Glib::path_get_dirname (*i));
-                                               vector<string> v;
-                                               v.push_back (to_dir);
-                                               v.push_back (interchange_dir_name);
-                                               v.push_back (new_folder);
-                                               v.push_back (typedir);
-                                               v.push_back (Glib::path_get_basename (*i));
-                                               
-                                               std::string to = Glib::build_filename (v);
-                                               
+                                               string to = make_new_media_path (*i, to_dir, new_folder);
+
                                                if (!copy_file (from, to)) {
                                                        throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
                                                }
@@ -4083,6 +4151,10 @@ Session::save_as (SaveAs& saveas)
                                        if (do_copy) {
                                                string to = Glib::build_filename (to_dir, (*i).substr (prefix_len));
                                                
+                                               if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
+                                                       throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
+                                               }
+                                               
                                                if (!copy_file (from, to)) {
                                                        throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
                                                }
@@ -4114,6 +4186,7 @@ Session::save_as (SaveAs& saveas)
                                        throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
                                }
                        }
+
                }
 
                _path = to_dir;
@@ -4182,6 +4255,20 @@ Session::save_as (SaveAs& saveas)
                        /* ensure that all existing tracks reset their current capture source paths 
                         */
                        reset_write_sources (true, true);
+
+                       /* the copying above was based on actually discovering files, not just iterating over the sources list.
+                          But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
+                       */
+
+                       for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
+                               boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
+                               if (!fs) {
+                                       continue;
+                               }
+
+                               string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
+                               fs->set_path (newpath);
+                       }
                }
 
        } catch (Glib::FileError& e) {