diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 785e5ff0c2..9018fdc08b 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -409,7 +409,21 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop framecnt_t worst_input_latency () const { return _worst_input_latency; } framecnt_t worst_track_latency () const { return _worst_track_latency; } framecnt_t worst_playback_latency () const { return _worst_output_latency + _worst_track_latency; } + + int consolidate_all_media (); + struct SaveAs { + std::string new_parent_folder; + std::string new_name; + bool switch_to; + bool copy_media; + bool copy_external; + + /* emitted as we make progress */ + PBD::Signal3 Progress; + }; + + int save_as (SaveAs&); int save_state (std::string snapshot_name, bool pending = false, bool switch_to_snapshot = false); int restore_state (std::string snapshot_name); int save_template (std::string template_name); @@ -418,7 +432,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop void remove_state (std::string snapshot_name); void rename_state (std::string old_name, std::string new_name); void remove_pending_capture_state (); - int rename (const std::string&); + int rename (const std::string&, bool after_copy = false); bool get_nsm_state () const { return _under_nsm_control; } void set_nsm_state (bool state) { _under_nsm_control = state; } bool save_default_options (); diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 97373d1402..1bc3a962a0 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -58,6 +58,7 @@ #include #include +#include #include @@ -3664,7 +3665,7 @@ Session::solo_cut_control() const } int -Session::rename (const std::string& new_name) +Session::rename (const std::string& new_name, bool after_copy) { string legal_name = legalize_for_path (new_name); string newpath; @@ -3808,11 +3809,12 @@ Session::rename (const std::string& new_name) } } - /* remove old name from recent sessions */ + if (!after_copy) { + /* remove old name from recent sessions */ + remove_recent_sessions (_path); + _path = newpath; + } - remove_recent_sessions (_path); - - _path = newpath; _current_snapshot_name = new_name; _name = new_name; @@ -3988,3 +3990,136 @@ Session::bring_all_sources_into_session (boost::function 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); + int64_t total_bytes = 0; + int64_t copied = 0; + int64_t cnt = 0; + int64_t all = 0; + + /* get total size */ + + for (vector::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) { + + /* need to clear this because + * find_files_matching_filter() is cumulative + */ + + files.clear (); + + find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true); + + all += files.size(); + + for (vector::iterator i = files.begin(); i != files.end(); ++i) { + GStatBuf gsb; + + if ((*i).find (X_("interchange")) == string::npos || saveas.copy_media) { + g_stat ((*i).c_str(), &gsb); + total_bytes += gsb.st_size; + } + } + } + + try { + for (vector::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) { + + /* need to clear this because + * find_files_matching_filter() is cumulative + */ + + files.clear (); + + find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true); + + const size_t prefix_len = (*sd).path.size(); + + for (vector::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) { + + GStatBuf gsb; + g_stat ((*i).c_str(), &gsb); + + if (!copy_file (from, to)) { + throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed"); + } + + copied += gsb.st_size; + double fraction = (double) copied / total_bytes; + + /* tell someone "X percent, file M of + * N"; M is one-based + */ + + cnt++; + + if (!saveas.Progress (fraction, cnt, all)) { + throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled"); + } + } + } + + /* 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 = 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"); + } + + if (saveas.copy_media && saveas.copy_external) { + if (consolidate_all_media()) { + throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed"); + } + } + } + + } catch (...) { + + /* recursively remove all the directories */ + + /* XXX HOW TO DO THIS */ + + /* return error */ + + return -1; + } + + return 0; +} + + +/** Check all sources used by the current snapshot + * and make a copy of any external media within + * the session. + */ +int +Session::consolidate_all_media () +{ + return 0; +}