some more information output to log during save-as, for debugging
[ardour.git] / libs / ardour / session_state.cc
index c514aa9861b077abc8ea010ae90cfed2d151cbf4..03acb63f0e0debe3ef368862fe197afe58842ff3 100644 (file)
@@ -54,6 +54,7 @@
 
 #include <glibmm.h>
 #include <glibmm/threads.h>
+#include <glibmm/fileutils.h>
 
 #include <boost/algorithm/string.hpp>
 
@@ -139,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));
@@ -663,7 +658,7 @@ Session::remove_state (string snapshot_name)
 
 /** @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());
@@ -701,7 +696,11 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot
 
        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;
@@ -731,8 +730,8 @@ 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;
                if (g_remove (tmp_path.c_str()) != 0) {
@@ -743,6 +742,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;
@@ -1852,6 +1853,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)
 {
@@ -2772,6 +2789,16 @@ 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 () ) {
+                                                       all_sources.erase (j);
+                                                       break;
+                                               }
+                                       }
                                }
                        }
                }
@@ -3064,6 +3091,10 @@ Session::controllable_by_descriptor (const ControllableDescriptor& desc)
                c = r->gain_control ();
                break;
 
+       case ControllableDescriptor::Trim:
+               c = r->trim()->gain_control ();
+               break;
+
        case ControllableDescriptor::Solo:
                 c = r->solo_control();
                break;
@@ -3617,13 +3648,24 @@ int
 Session::rename (const std::string& new_name)
 {
        string legal_name = legalize_for_path (new_name);
-       string newpath;
+       string new_path;
        string oldstr;
        string newstr;
        bool first = true;
 
        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
@@ -3638,124 +3680,145 @@ Session::rename (const std::string& new_name)
         * already exist ...
         */
 
-       vector<space_and_path> new_session_dirs;
-
        for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
-               vector<string> v;
-
+               
                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);
                
+               cerr << "Looking for " << newstr << endl;
+               
                if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
+                       cerr << " exists\n";
                        return -1;
                }
-
-               space_and_path sp;
-               sp.path = newstr;
-               sp.blocks = 0; // not needed
-               new_session_dirs.push_back(sp);
        }
 
        /* Session dirs */
 
-       for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
+       first = true;
+       
+       for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
+
                vector<string> v;
 
                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);
 
+               cerr << "for " << oldstr << " new dir = " << newstr << endl;
+               
                cerr << "Rename " << oldstr << " => " << newstr << endl;                
-
                if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
-                       error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
+                       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) {
                        (*_session_dir) = newstr;
-                       newpath = newstr;
-                       first = 1;
+                       new_path = newstr;
+                       first = false;
                }
 
-               /* directory below interchange */
+               /* now rename directory below session_dir/interchange */
 
-               v.push_back (newstr);
+               string old_interchange_dir;
+               string new_interchange_dir;
+
+               /* 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 (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);
                
-               cerr << "Rename " << oldstr << " => " << newstr << endl;
+               new_interchange_dir = Glib::build_filename (v);
                
-               if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
-                       error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
+               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))
+                             << endmsg;
                        return 1;
                }
        }
 
-       session_dirs = new_session_dirs;
-
        /* 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;                
 
        if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
+               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;
        }
 
        /* 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;                
                
                if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
+                       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;
                }
        }
 
+       /* 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) {
@@ -3768,26 +3831,15 @@ Session::rename (const std::string& new_name)
                }
        }
 
-       /* remove old name from recent sessions */
-
-       remove_recent_sessions (_path);
-
-       _path = newpath;
        _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);
@@ -3887,7 +3939,6 @@ Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,
                        }
                        
                        if (fs->within_session()) {
-                               cerr << "skip " << fs->name() << endl;
                                continue;
                        }
                        
@@ -3922,9 +3973,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)) {
@@ -3948,3 +4004,359 @@ Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,
 
        return ret;
 }
+
+static
+bool accept_all_files (string const &, void *)
+{
+       return true;
+}
+
+void
+Session::save_as_bring_callback (uint32_t,uint32_t,string)
+{
+       /* It would be good if this did something useful vis-a-vis save-as, but the arguments doesn't provide the correct information right now to do this.
+       */
+}
+
+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)
+{
+       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, new_folder);
+       int64_t total_bytes = 0;
+       int64_t copied = 0;
+       int64_t cnt = 0;
+       int64_t all = 0;
+       int32_t internal_file_cnt = 0;
+
+       vector<string> do_not_copy_extensions;
+       do_not_copy_extensions.push_back (statefile_suffix);
+       do_not_copy_extensions.push_back (pending_suffix);
+       do_not_copy_extensions.push_back (backup_suffix);
+       do_not_copy_extensions.push_back (temp_suffix);
+       do_not_copy_extensions.push_back (history_suffix);
+
+       /* get total size */
+
+       for (vector<space_and_path>::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<string>::iterator i = files.begin(); i != files.end(); ++i) {
+                       GStatBuf gsb;
+                       g_stat ((*i).c_str(), &gsb);
+                       total_bytes += gsb.st_size;
+               }
+       }
+
+       /* save old values so we can switch back if we are not switching to the new session */
+       
+       string old_path = _path;
+       string old_name = _name;
+       string old_snapshot = _current_snapshot_name;
+       string old_sd = _session_dir->root_path();
+       vector<string> old_search_path[DataType::num_types];
+       string old_config_search_path[DataType::num_types];
+
+       old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
+       old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
+       old_config_search_path[DataType::AUDIO]  = config.get_audio_search_path ();     
+       old_config_search_path[DataType::MIDI]  = config.get_midi_search_path ();       
+
+       /* switch session directory */
+       
+       (*_session_dir) = to_dir;
+
+       /* 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 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) {
+                       
+                       /* need to clear this because
+                        * find_files_matching_filter() is cumulative
+                        */
+                       
+                       files.clear ();
+                       
+                       const size_t prefix_len = (*sd).path.size();
+                       
+                       /* Work just on the files within this session dir */
+                       
+                       find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
+                       
+                       /* copy all the files. Handling is different for media files
+                          than others because of the *silly* subtree we have below the interchange
+                          folder. That really was a bad idea, but I'm not fixing it as part of
+                          implementing ::save_as().
+                       */
+                       
+                       for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
+
+                               std::string from = *i;
+                               
+                               if ((*i).find (interchange_dir_name) != string::npos) {
+                                       
+                                       /* media file */
+
+                                       if (saveas.include_media && saveas.copy_media) {
+                                               
+                                               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");
+                                               }
+                                       }
+                                       
+                                       /* we found media files inside the session folder */
+                                       
+                                       internal_file_cnt++;
+                                       
+                               } else {
+                                       
+                                       /* normal non-media file. Don't copy state, history, etc.
+                                        */
+                                       
+                                       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())) {
+                                                       /* end of filename matches extension, do not copy file */
+                                                       do_copy = false;
+                                                       break;
+                                               } 
+                                       }
+                                       
+                                       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");
+                                               }
+                                       }
+                               }
+                               
+                               /* measure file size even if we're not going to copy so that our Progress
+                                  signals are correct, since we included these do-not-copy files
+                                  in the computation of the total size and file count.
+                               */
+                               
+                               GStatBuf gsb;
+                               g_stat ((*i).c_str(), &gsb);
+                               copied += gsb.st_size;
+                               cnt++;
+                               
+                               double fraction = (double) copied / total_bytes;
+                               
+                               /* tell someone "X percent, file M of N"; M is one-based */
+                               
+                               boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
+                               bool keep_going = true;
+
+                               if (res) {
+                                       keep_going = *res;
+                               }
+
+                               if (!keep_going) {
+                                       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.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) {
+                                       ensure_search_path_includes (*s, DataType::MIDI);
+                               }
+                       }
+               }
+               
+               bool was_dirty = dirty ();
+
+               save_state ("", false, false, !saveas.include_media);
+               save_default_options ();
+               
+               if (saveas.copy_media && saveas.copy_external) {
+                       if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
+                               throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
+                       }
+               }
+
+               saveas.final_session_folder_name = _path;
+               
+               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 ();
+                       }
+
+                       if (internal_file_cnt) {
+                               /* reset these to their original values */
+                               config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
+                               config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
+                       }
+                       
+               } else {
+
+                       /* prune session dirs, and update disk space statistics
+                        */
+
+                       space_and_path sp;
+                       sp.path = _path;
+                       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) {
+
+               saveas.failure_message = e.what();
+               
+               /* recursively remove all the directories */
+               
+               remove_directory (to_dir);
+               
+               /* return error */
+               
+               return -1;
+
+       } catch (...) {
+
+               saveas.failure_message = _("unknown reason");
+               
+               /* recursively remove all the directories */
+               
+               remove_directory (to_dir);
+               
+               /* return error */
+               
+               return -1;
+       }
+       
+       return 0;
+}