first working version of save-as
This commit is contained in:
parent
2866514c09
commit
08d56360d6
@ -2285,7 +2285,18 @@ ARDOUR_UI::stop_clocking ()
|
||||
void
|
||||
ARDOUR_UI::save_session_as ()
|
||||
{
|
||||
if (!_session) {
|
||||
return;
|
||||
}
|
||||
|
||||
Session::SaveAs sa;
|
||||
sa.new_parent_folder = "/tmp";
|
||||
sa.new_name = "foobar";
|
||||
sa.switch_to = true;
|
||||
sa.copy_media = true;
|
||||
sa.copy_external = false;
|
||||
|
||||
_session->save_as (sa);
|
||||
}
|
||||
|
||||
/** Ask the user for the name of a new snapshot and then take it.
|
||||
|
@ -46,7 +46,7 @@ class LIBARDOUR_API FileSource : virtual public Source {
|
||||
public:
|
||||
virtual ~FileSource ();
|
||||
|
||||
virtual const std::string& path() const { return _path; }
|
||||
const std::string& path() const { return _path; }
|
||||
|
||||
virtual bool safe_file_extension (const std::string& path) const = 0;
|
||||
|
||||
|
@ -140,12 +140,6 @@ Session::pre_engine_init (string fullpath)
|
||||
|
||||
_path = canonical_path(fullpath);
|
||||
|
||||
/* we require _path to end with a dir separator */
|
||||
|
||||
if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
|
||||
_path += G_DIR_SEPARATOR;
|
||||
}
|
||||
|
||||
/* is it new ? */
|
||||
|
||||
_is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
|
||||
@ -731,7 +725,7 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot
|
||||
std::string tmp_path(_session_dir->root_path());
|
||||
tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
|
||||
|
||||
// cerr << "actually writing state to " << xml_path << endl;
|
||||
cerr << "actually writing state to " << tmp_path << endl;
|
||||
|
||||
if (!tree.write (tmp_path)) {
|
||||
error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
|
||||
@ -743,6 +737,8 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot
|
||||
|
||||
} else {
|
||||
|
||||
cerr << "renaming state to " << xml_path << endl;
|
||||
|
||||
if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
|
||||
error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
|
||||
tmp_path, xml_path, g_strerror(errno)) << endmsg;
|
||||
@ -3602,7 +3598,7 @@ int
|
||||
Session::rename (const std::string& new_name, bool after_copy)
|
||||
{
|
||||
string legal_name = legalize_for_path (new_name);
|
||||
string newpath;
|
||||
string new_path;
|
||||
string oldstr;
|
||||
string newstr;
|
||||
bool first = true;
|
||||
@ -3623,9 +3619,14 @@ Session::rename (const std::string& new_name, bool after_copy)
|
||||
* already exist ...
|
||||
*/
|
||||
|
||||
if (!after_copy) {
|
||||
for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
|
||||
vector<string> v;
|
||||
|
||||
if (first) {
|
||||
/* primary session directory */
|
||||
newstr = _path;
|
||||
first = false;
|
||||
} else {
|
||||
oldstr = (*i).path;
|
||||
|
||||
/* this is a stupid hack because Glib::path_get_dirname() is
|
||||
@ -3641,15 +3642,19 @@ Session::rename (const std::string& new_name, bool after_copy)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Session dirs */
|
||||
|
||||
for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
|
||||
first = false;
|
||||
|
||||
for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
|
||||
vector<string> v;
|
||||
|
||||
oldstr = (*i).path;
|
||||
@ -3663,51 +3668,68 @@ Session::rename (const std::string& new_name, bool after_copy)
|
||||
oldstr = oldstr.substr (0, oldstr.length() - 1);
|
||||
}
|
||||
|
||||
if (first) {
|
||||
newstr = _path;
|
||||
} else {
|
||||
string base = Glib::path_get_dirname (oldstr);
|
||||
string p = Glib::path_get_basename (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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset path in "session dirs" */
|
||||
|
||||
(*i).path = newstr;
|
||||
|
||||
/* reset primary SessionDirectory object */
|
||||
|
||||
if (first) {
|
||||
(*_session_dir) = newstr;
|
||||
newpath = newstr;
|
||||
first = 1;
|
||||
new_path = newstr;
|
||||
first = false;
|
||||
}
|
||||
|
||||
/* directory below interchange */
|
||||
/* now rename directory below session_dir/interchange */
|
||||
|
||||
string old_interchange_dir;
|
||||
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 (p);
|
||||
v.push_back (Glib::path_get_basename (oldstr));
|
||||
|
||||
oldstr = Glib::build_filename (v);
|
||||
old_interchange_dir = Glib::build_filename (v);
|
||||
|
||||
v.clear ();
|
||||
v.push_back (newstr);
|
||||
v.push_back (interchange_dir_name);
|
||||
v.push_back (legal_name);
|
||||
|
||||
newstr = Glib::build_filename (v);
|
||||
new_interchange_dir = Glib::build_filename (v);
|
||||
|
||||
cerr << "Rename " << oldstr << " => " << newstr << endl;
|
||||
cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << 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;
|
||||
if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
|
||||
error << string_compose (_("renaming %s as %2 failed (%3)"),
|
||||
old_interchange_dir, new_interchange_dir,
|
||||
g_strerror (errno))
|
||||
<< endmsg;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* state file */
|
||||
|
||||
oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
|
||||
newstr= Glib::build_filename (newpath, 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;
|
||||
|
||||
@ -3718,11 +3740,10 @@ Session::rename (const std::string& new_name, bool after_copy)
|
||||
|
||||
/* history file */
|
||||
|
||||
|
||||
oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
|
||||
oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
|
||||
|
||||
if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
|
||||
newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
|
||||
newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
|
||||
|
||||
cerr << "Rename " << oldstr << " => " << newstr << endl;
|
||||
|
||||
@ -3732,38 +3753,21 @@ Session::rename (const std::string& new_name, bool after_copy)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
if (!after_copy) {
|
||||
/* remove old name from recent sessions */
|
||||
remove_recent_sessions (_path);
|
||||
_path = newpath;
|
||||
_path = new_path;
|
||||
}
|
||||
|
||||
_current_snapshot_name = new_name;
|
||||
_name = new_name;
|
||||
|
||||
/* re-add directory separator - reverse hack to oldstr above */
|
||||
if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
|
||||
_path += G_DIR_SEPARATOR;
|
||||
}
|
||||
|
||||
set_dirty ();
|
||||
|
||||
/* save state again to get everything just right */
|
||||
|
||||
save_state (_current_snapshot_name);
|
||||
|
||||
|
||||
/* add to recent sessions */
|
||||
|
||||
store_recent_sessions (new_name, _path);
|
||||
@ -3937,7 +3941,7 @@ Session::save_as (SaveAs& saveas)
|
||||
vector<string> files;
|
||||
string current_folder = Glib::path_get_dirname (_path);
|
||||
string new_folder = legalize_for_path (saveas.new_name);
|
||||
string to_dir = Glib::build_filename (saveas.new_parent_folder, saveas.new_name);
|
||||
string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
|
||||
int64_t total_bytes = 0;
|
||||
int64_t copied = 0;
|
||||
int64_t cnt = 0;
|
||||
@ -3957,6 +3961,8 @@ Session::save_as (SaveAs& saveas)
|
||||
|
||||
all += files.size();
|
||||
|
||||
cerr << (*sd).path << " Contained " << files.size() << " total now " << all << endl;
|
||||
|
||||
for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
|
||||
GStatBuf gsb;
|
||||
|
||||
@ -3965,9 +3971,32 @@ Session::save_as (SaveAs& saveas)
|
||||
total_bytes += gsb.st_size;
|
||||
}
|
||||
}
|
||||
cerr << "\ttotal size now " << total_bytes << endl;
|
||||
}
|
||||
|
||||
/* Create the new session directory */
|
||||
|
||||
string old_path = _path;
|
||||
string old_name = _name;
|
||||
string old_snapshot = _current_snapshot_name;
|
||||
string old_sd = _session_dir->root_path();
|
||||
|
||||
(*_session_dir) = to_dir;
|
||||
|
||||
if (!_session_dir->create()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cerr << "Created new session dir " << _session_dir->root_path() << endl;
|
||||
|
||||
try {
|
||||
if (saveas.copy_media) {
|
||||
|
||||
/* copy all media 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) {
|
||||
|
||||
/* need to clear this because
|
||||
@ -3980,17 +4009,30 @@ Session::save_as (SaveAs& saveas)
|
||||
|
||||
const size_t prefix_len = (*sd).path.size();
|
||||
|
||||
/* copy all media files (everything below
|
||||
* interchange/)
|
||||
*/
|
||||
|
||||
for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
|
||||
std::string from = *i;
|
||||
std::string to = Glib::build_filename (to_dir, (*i).substr(prefix_len));
|
||||
|
||||
g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755);
|
||||
|
||||
if ((*i).find (X_("interchange")) == string::npos || saveas.copy_media) {
|
||||
if ((*i).find (X_("interchange")) != string::npos) {
|
||||
|
||||
/* media file */
|
||||
|
||||
GStatBuf gsb;
|
||||
g_stat ((*i).c_str(), &gsb);
|
||||
|
||||
/* strip the session dir prefix from
|
||||
* each full path, then prepend new
|
||||
* to_dir to give complete path.
|
||||
*/
|
||||
|
||||
std::string to = Glib::build_filename (to_dir, (*i).substr (prefix_len));
|
||||
|
||||
cerr << "Copy " << from << " to " << to << endl;
|
||||
|
||||
if (!copy_file (from, to)) {
|
||||
throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
|
||||
}
|
||||
@ -4004,45 +4046,126 @@ Session::save_as (SaveAs& saveas)
|
||||
|
||||
cnt++;
|
||||
|
||||
cerr << "PROGRESS " << fraction << "%, " << cnt << " of " << all << endl;
|
||||
|
||||
#if 0
|
||||
if (!saveas.Progress (fraction, cnt, all)) {
|
||||
throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now modify our _path setting so that we refer to the copy we've just
|
||||
* created. The filename of the session file hasn't
|
||||
* been changed yet.
|
||||
_path = to_dir;
|
||||
_current_snapshot_name = saveas.new_name;
|
||||
_name = saveas.new_name;
|
||||
|
||||
cerr << "New path = " << _path << endl;
|
||||
|
||||
if (!saveas.copy_media && saveas.switch_to) {
|
||||
|
||||
/* need to make all internal file sources point to old session */
|
||||
|
||||
for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
|
||||
boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
|
||||
|
||||
if (fs && fs->within_session()) {
|
||||
|
||||
cerr << "fs " << fs->name() << " is inside session " << fs->path() << endl;
|
||||
|
||||
/* give it an absolute path referencing
|
||||
* the original session. Should be
|
||||
* easy, but in general, we don't
|
||||
* actually know where it lives - it
|
||||
* could be in any session dir. So we
|
||||
* have to look for it.
|
||||
*
|
||||
* Note that the session_dirs list
|
||||
*/
|
||||
|
||||
_path = new_folder;
|
||||
|
||||
/* _path now refers to the copy we just created, but that copy
|
||||
* contains references to the wrong name and so forth.
|
||||
* Use rename() to actually change the name
|
||||
*/
|
||||
|
||||
if (rename (saveas.new_name, true)) {
|
||||
throw Glib::FileError (Glib::FileError::NAME_TOO_LONG, "rename failed");
|
||||
for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
|
||||
SessionDirectory sdir ((*sd).path);
|
||||
string file_dir;
|
||||
switch (fs->type()) {
|
||||
case DataType::AUDIO:
|
||||
file_dir = sdir.sound_path();
|
||||
break;
|
||||
case DataType::MIDI:
|
||||
file_dir = sdir.midi_path();
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
string possible_path = Glib::build_filename (file_dir, fs->path());
|
||||
if (Glib::file_test (possible_path, Glib::FILE_TEST_EXISTS)) {
|
||||
/* Found it */
|
||||
cerr << "Reset path for " << fs->name() << " @ " << fs->path() << " to " << possible_path << endl;
|
||||
fs->set_path (possible_path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool was_dirty = dirty ();
|
||||
|
||||
cerr << "Saving state\n";
|
||||
|
||||
save_state ("", false, false);
|
||||
save_default_options ();
|
||||
|
||||
if (saveas.copy_media && saveas.copy_external) {
|
||||
if (consolidate_all_media()) {
|
||||
throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (!saveas.switch_to) {
|
||||
|
||||
/* switch back to the way things were */
|
||||
|
||||
_path = old_path;
|
||||
_name = old_name;
|
||||
_current_snapshot_name = old_snapshot;
|
||||
|
||||
(*_session_dir) = old_sd;
|
||||
|
||||
if (was_dirty) {
|
||||
set_dirty ();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* prune session dirs
|
||||
*/
|
||||
|
||||
space_and_path sp;
|
||||
sp.path = _path;
|
||||
session_dirs.clear ();
|
||||
session_dirs.push_back (sp);
|
||||
refresh_disk_space ();
|
||||
|
||||
cerr << "pruned session dirs, sd = " << _session_dir->root_path()
|
||||
<< " path = " << _path << endl;
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
|
||||
cerr << "copying/saveas failed\n";
|
||||
|
||||
/* recursively remove all the directories */
|
||||
|
||||
/* XXX HOW TO DO THIS */
|
||||
remove_directory (to_dir);
|
||||
|
||||
/* return error */
|
||||
|
||||
return -1;
|
||||
}
|
||||
cerr << "saveas completed successfully\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user