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));
/** @param snapshot_name Name to save under, without .ardour / .pending prefix */
int
-Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
+Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
{
XMLTree tree;
std::string xml_path(_session_dir->root_path());
}
}
- SaveSession (); /* EMIT SIGNAL */
+ SessionSaveUnderway (); /* EMIT SIGNAL */
- tree.set_root (&get_state());
+ if (template_only) {
+ tree.set_root (&get_template());
+ } else {
+ tree.set_root (&get_state());
+ }
if (snapshot_name.empty()) {
snapshot_name = _current_snapshot_name;
int
Session::load_options (const XMLNode& node)
{
- LocaleGuard lg (X_("POSIX"));
+ LocaleGuard lg (X_("C"));
config.set_variables (node);
return 0;
}
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;
}
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)
{
_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;
_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)
{
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 () ) {
+ all_sources.erase (j);
+ break;
+ }
+ }
}
}
}
c = r->gain_control ();
break;
+ case ControllableDescriptor::Trim:
+ c = r->trim()->gain_control ();
+ break;
+
case ControllableDescriptor::Solo:
c = r->solo_control();
break;
}
int
-Session::rename (const std::string& new_name, bool after_copy)
+Session::rename (const std::string& new_name)
{
string legal_name = legalize_for_path (new_name);
string new_path;
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
* already exist ...
*/
- if (!after_copy) {
- for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
-
- if (first) {
- /* primary session directory */
- newstr = _path;
- first = false;
- } else {
- oldstr = (*i).path;
-
- /* this is a stupid hack because Glib::path_get_dirname() is
- * lexical-only, and so passing it /a/b/c/ gives a different
- * result than passing it /a/b/c ...
- */
-
- if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
- oldstr = oldstr.substr (0, oldstr.length() - 1);
- }
-
- string base = Glib::path_get_dirname (oldstr);
- string p = Glib::path_get_basename (oldstr);
-
- newstr = Glib::build_filename (base, legal_name);
- }
-
- if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
- return -1;
- }
+ for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
+
+ oldstr = (*i).path;
+
+ /* this is a stupid hack because Glib::path_get_dirname() is
+ * lexical-only, and so passing it /a/b/c/ gives a different
+ * result than passing it /a/b/c ...
+ */
+
+ if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
+ oldstr = oldstr.substr (0, oldstr.length() - 1);
+ }
+
+ string base = Glib::path_get_dirname (oldstr);
+
+ newstr = Glib::build_filename (base, legal_name);
+
+ cerr << "Looking for " << newstr << endl;
+
+ if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
+ cerr << " exists\n";
+ return -1;
}
}
/* Session dirs */
- first = false;
+ first = true;
for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
+
vector<string> v;
oldstr = (*i).path;
oldstr = oldstr.substr (0, oldstr.length() - 1);
}
- if (first) {
- newstr = _path;
- } else {
- string base = Glib::path_get_dirname (oldstr);
- newstr = Glib::build_filename (base, legal_name);
- }
+ string base = Glib::path_get_dirname (oldstr);
+ newstr = Glib::build_filename (base, legal_name);
- if (!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;
- return 1;
- }
+ cerr << "for " << oldstr << " new dir = " << newstr << endl;
+
+ cerr << "Rename " << oldstr << " => " << newstr << endl;
+ if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
+ cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
+ error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
+ return 1;
}
/* Reset path in "session dirs" */
(*i).path = newstr;
-
+ (*i).blocks = 0;
+
/* reset primary SessionDirectory object */
if (first) {
string old_interchange_dir;
string new_interchange_dir;
- /* use newstr here because we renamed the path that used to be oldstr to newstr above */
-
+ /* use newstr here because we renamed the path
+ * (folder/directory) 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));
cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
+ cerr << string_compose (_("renaming %s as %2 failed (%3)"),
+ old_interchange_dir, new_interchange_dir,
+ g_strerror (errno))
+ << endl;
error << string_compose (_("renaming %s as %2 failed (%3)"),
old_interchange_dir, new_interchange_dir,
g_strerror (errno))
/* state file */
- oldstr = Glib::build_filename (new_path, _current_snapshot_name) + statefile_suffix;
- newstr= Glib::build_filename (new_path, legal_name) + statefile_suffix;
+ oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
+ newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
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;
+ cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
+ error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
return 1;
}
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;
+ cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
+ error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
return 1;
}
}
- if (!after_copy) {
- /* remove old name from recent sessions */
- remove_recent_sessions (_path);
- _path = new_path;
+ /* 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;
_name = new_name;
-
+
set_dirty ();
/* save state again to get everything just right */
}
if (fs->within_session()) {
- cerr << "skip " << fs->name() << endl;
continue;
}
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)) {
*/
}
+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)
{
/* create new tree */
if (!_session_dir->create()) {
+ saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
return -1;
}
try {
- /* copy all media files. Find each location in
- * session_dirs, and copy files from there to
- * target.
+ /* copy all relevant files. Find each location in session_dirs,
+ * and copy files from there to target.
*/
for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
/* media file */
- if (saveas.copy_media) {
+ if (saveas.include_media && 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);
+
+ info << "media file copying from " << from << " to " << to << endmsg;
if (!copy_file (from, to)) {
throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
if (do_copy) {
string to = Glib::build_filename (to_dir, (*i).substr (prefix_len));
+ info << "attempting to make directory/folder " << to << endmsg;
+
+ if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
+ throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
+ }
+
+ 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::FAILED, "copy cancelled");
}
}
+
+ }
+
+ /* copy optional folders, if any */
+
+ string old = plugins_dir ();
+ if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
+ string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
+ copy_files (old, newdir);
+ }
+
+ old = externals_dir ();
+ if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
+ string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
+ copy_files (old, newdir);
}
+ old = automation_dir ();
+ if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
+ string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
+ copy_files (old, newdir);
+ }
+
+ if (saveas.include_media) {
+
+ if (saveas.copy_media) {
+
+ /* only needed if we are copying media, since the
+ * analysis data refers to media data
+ */
+
+ old = analysis_dir ();
+ if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
+ string newdir = Glib::build_filename (to_dir, "analysis");
+ copy_files (old, newdir);
+ }
+ }
+ }
+
+
_path = to_dir;
_current_snapshot_name = saveas.new_name;
_name = saveas.new_name;
- if (!saveas.copy_media) {
+ if (saveas.include_media && !saveas.copy_media) {
/* reset search paths of the new session (which we're pretending to be right now) to
include the original session search path, so we can still find all audio.
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;
}
for (vector<string>::iterator s = old_search_path[DataType::MIDI].begin(); s != old_search_path[DataType::MIDI].end(); ++s) {
bool was_dirty = dirty ();
- save_state ("", false, false);
+ save_state ("", false, false, !saveas.include_media);
save_default_options ();
if (saveas.copy_media && saveas.copy_external) {
}
}
+ saveas.final_session_folder_name = _path;
+
if (!saveas.switch_to) {
/* switch back to the way things were */
session_dirs.clear ();
session_dirs.push_back (sp);
refresh_disk_space ();
+
+ /* 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;
+ }
+
+ if (fs->within_session()) {
+ string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
+ fs->set_path (newpath);
+ }
+ }
}
} catch (Glib::FileError& e) {