diff options
Diffstat (limited to 'libs/ardour/session_state.cc')
-rw-r--r-- | libs/ardour/session_state.cc | 221 |
1 files changed, 155 insertions, 66 deletions
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 5333c9165c..82ee766b23 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -56,6 +56,7 @@ #include "midi++/manager.h" #include "pbd/boost_debug.h" +#include "pbd/basename.h" #include "pbd/controllable_descriptor.h" #include "pbd/enumwriter.h" #include "pbd/error.h" @@ -146,7 +147,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) _path = string(buf); - if (_path[_path.length()-1] != '/') { + if (_path[_path.length()-1] != G_DIR_SEPARATOR) { _path += G_DIR_SEPARATOR; } @@ -487,7 +488,7 @@ Session::ensure_subdirs () return -1; } - dir = session_directory().dead_sound_path().to_string(); + dir = session_directory().dead_path().to_string(); if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) { error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg; @@ -2415,18 +2416,46 @@ Session::commit_reversible_command (Command *cmd) } static bool -accept_all_non_peak_files (const string& path, void */*arg*/) +accept_all_non_stub_audio_files (const string& path, void */*arg*/) +{ + if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) { + return false; + } + + if (FileSource::is_stub_path (path)) { + return false; + } + + if (!AudioFileSource::safe_audio_file_extension (path)) { + return false; + } + + return true; +} + +static bool +accept_all_non_stub_midi_files (const string& path, void */*arg*/) { if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) { return false; } - return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5)); + if (FileSource::is_stub_path (path)) { + return false; + } + + return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) || + (path.length() > 4 && path.find (".smf") != (path.length() - 4)) || + (path.length() > 5 && path.find (".midi") != (path.length() - 5))); } static bool accept_all_state_files (const string& path, void */*arg*/) { + if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) { + return false; + } + return (path.length() > 7 && path.find (".ardour") == (path.length() - 7)); } @@ -2572,10 +2601,12 @@ Session::cleanup_sources (CleanupReport& rep) vector<boost::shared_ptr<Source> > dead_sources; PathScanner scanner; - string sound_path; + string audio_path; + string midi_path; vector<space_and_path>::iterator i; vector<space_and_path>::iterator nexti; - vector<string*>* soundfiles; + vector<string*>* candidates; + vector<string*>* candidates2; vector<string> unused; set<string> all_sources; bool used; @@ -2584,14 +2615,19 @@ Session::cleanup_sources (CleanupReport& rep) _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup); - /* step 1: consider deleting all unused playlists */ + /* consider deleting all unused playlists */ if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) { ret = 0; goto out; } - /* step 2: find all un-used sources */ + /* sync the "all regions" property of each playlist with its current state + */ + + playlists->sync_all_regions_with_regions (); + + /* find all un-used sources */ rep.paths.clear (); rep.space = 0; @@ -2615,7 +2651,7 @@ Session::cleanup_sources (CleanupReport& rep) i = tmp; } - /* build a list of all the possible sound directories for the session */ + /* build a list of all the possible audio directories for the session */ for (i = session_dirs.begin(); i != session_dirs.end(); ) { @@ -2623,25 +2659,49 @@ Session::cleanup_sources (CleanupReport& rep) ++nexti; SessionDirectory sdir ((*i).path); - sound_path += sdir.sound_path().to_string(); + audio_path += sdir.sound_path().to_string(); if (nexti != session_dirs.end()) { - sound_path += ':'; + audio_path += ':'; } i = nexti; } - /* now do the same thing for the files that ended up in the sounds dir(s) - but are not referenced as sources in any snapshot. - */ - soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true); + /* build a list of all the possible midi directories for the session */ - if (soundfiles == 0) { - return 0; + for (i = session_dirs.begin(); i != session_dirs.end(); ) { + + nexti = i; + ++nexti; + + SessionDirectory sdir ((*i).path); + midi_path += sdir.midi_path().to_string(); + + if (nexti != session_dirs.end()) { + midi_path += ':'; + } + + i = nexti; } + candidates = scanner (audio_path, accept_all_non_stub_audio_files, (void *) 0, true, true); + candidates2 = scanner (midi_path, accept_all_non_stub_midi_files, (void *) 0, true, true); + + /* merge them */ + + if (candidates) { + if (candidates2) { + for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) { + candidates->push_back (*i); + } + delete candidates2; + } + } else { + candidates = candidates2; // might still be null + } + /* find all sources, but don't use this snapshot because the state file on disk still references sources we may have already dropped. @@ -2652,61 +2712,82 @@ Session::cleanup_sources (CleanupReport& rep) /* add our current source list */ - for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) { + for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) { boost::shared_ptr<FileSource> fs; + SourceMap::iterator tmp = i; + ++tmp; if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) { - all_sources.insert (fs->path()); + if (!fs->is_stub()) { + if (playlists->source_use_count (fs) != 0) { + all_sources.insert (fs->path()); + } else { + + /* we might not remove this source from disk, because it may be used + by other snapshots, but its not being used in this version + so lets get rid of it now, along with any representative regions + in the region list. + */ + + cerr << "Source " << i->second->name() << "ID " << i->second->id() << " not used, remove from source list and also all regions\n"; + + RegionFactory::remove_regions_using_source (i->second); + sources.erase (i); + } + } } + + i = tmp; } char tmppath1[PATH_MAX+1]; char tmppath2[PATH_MAX+1]; - for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) { - - used = false; - spath = **x; - - for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) { + if (candidates) { + for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) { + + used = false; + spath = **x; + + for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) { + + if (realpath(spath.c_str(), tmppath1) == 0) { + error << string_compose (_("Cannot expand path %1 (%2)"), + spath, strerror (errno)) << endmsg; + continue; + } + + if (realpath((*i).c_str(), tmppath2) == 0) { + error << string_compose (_("Cannot expand path %1 (%2)"), + (*i), strerror (errno)) << endmsg; + continue; + } - if (realpath(spath.c_str(), tmppath1) == 0) { - error << string_compose (_("Cannot expand path %1 (%2)"), - spath, strerror (errno)) << endmsg; - continue; + if (strcmp(tmppath1, tmppath2) == 0) { + used = true; + break; + } } - - if (realpath((*i).c_str(), tmppath2) == 0) { - error << string_compose (_("Cannot expand path %1 (%2)"), - (*i), strerror (errno)) << endmsg; - continue; + + if (!used) { + unused.push_back (spath); } - if (strcmp(tmppath1, tmppath2) == 0) { - used = true; - break; - } - } + delete *x; + } - if (!used) { - unused.push_back (spath); - } - } + delete candidates; + } - /* now try to move all unused files into the "dead_sounds" directory(ies) */ + /* now try to move all unused files into the "dead" directory(ies) */ for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) { struct stat statbuf; - rep.paths.push_back (*x); - if (stat ((*x).c_str(), &statbuf) == 0) { - rep.space += statbuf.st_size; - } - string newpath; /* don't move the file across filesystems, just - stick it in the `dead_sound_dir_name' directory + stick it in the `dead_dir_name' directory on whichever filesystem it was already on. */ @@ -2721,16 +2802,16 @@ Session::cleanup_sources (CleanupReport& rep) /* new school, go up 4 levels */ - newpath = Glib::path_get_dirname (*x); // "audiofiles" + newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles" newpath = Glib::path_get_dirname (newpath); // "session-name" newpath = Glib::path_get_dirname (newpath); // "interchange" newpath = Glib::path_get_dirname (newpath); // "session-dir" } - newpath = Glib::build_filename (newpath, dead_sound_dir_name); + newpath = Glib::build_filename (newpath, dead_dir_name); if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) { - error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg; + error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg; return -1; } @@ -2747,7 +2828,7 @@ Session::cleanup_sources (CleanupReport& rep) snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version); newpath_v = buf; - while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) { + while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) { snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version); newpath_v = buf; } @@ -2766,8 +2847,10 @@ Session::cleanup_sources (CleanupReport& rep) } + stat ((*x).c_str(), &statbuf); + if (::rename ((*x).c_str(), newpath.c_str()) != 0) { - error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"), + error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"), (*x), newpath, strerror (errno)) << endmsg; goto out; @@ -2776,22 +2859,27 @@ Session::cleanup_sources (CleanupReport& rep) /* see if there an easy to find peakfile for this file, and remove it. */ - string peakpath = (*x).substr (0, (*x).find_last_of ('.')); - peakpath += peakfile_suffix; - - if (access (peakpath.c_str(), W_OK) == 0) { + string base = basename_nosuffix (*x); + base += "%A"; /* this is what we add for the channel suffix of all native files, + or for the first channel of embedded files. it will miss + some peakfiles for other channels + */ + string peakpath = peak_path (base); + + if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) { if (::unlink (peakpath.c_str()) != 0) { error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"), - peakpath, _path, strerror (errno)) + peakpath, _path, strerror (errno)) << endmsg; /* try to back out */ rename (newpath.c_str(), _path.c_str()); goto out; } } - } - ret = 0; + rep.paths.push_back (*x); + rep.space += statbuf.st_size; + } /* dump the history list */ @@ -2802,6 +2890,7 @@ Session::cleanup_sources (CleanupReport& rep) */ save_state (""); + ret = 0; out: _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup); @@ -2815,17 +2904,17 @@ Session::cleanup_trash_sources (CleanupReport& rep) // FIXME: needs adaptation for MIDI vector<space_and_path>::iterator i; - string dead_sound_dir; + string dead_dir; rep.paths.clear (); rep.space = 0; for (i = session_dirs.begin(); i != session_dirs.end(); ++i) { - dead_sound_dir = (*i).path; - dead_sound_dir += dead_sound_dir_name; + dead_dir = (*i).path; + dead_dir += dead_dir_name; - clear_directory (dead_sound_dir, &rep.space, &rep.paths); + clear_directory (dead_dir, &rep.space, &rep.paths); } return 0; |