diff options
Diffstat (limited to 'libs/ardour/session_state.cc')
-rw-r--r-- | libs/ardour/session_state.cc | 170 |
1 files changed, 112 insertions, 58 deletions
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 95449d6c1a..2ae8a833e1 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -83,6 +83,7 @@ #include <ardour/control_protocol_manager.h> #include <ardour/region_factory.h> #include <ardour/source_factory.h> +#include <ardour/playlist_factory.h> #include <control_protocol/control_protocol.h> @@ -236,7 +237,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region)); SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source)); - Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist)); + PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist)); Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect)); NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection)); AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list)); @@ -380,6 +381,7 @@ Session::setup_raid_path (string path) if (fspath[fspath.length()-1] != '/') { fspath += '/'; } + fspath += sound_dir (false); AudioFileSource::set_search_path (fspath); @@ -1681,7 +1683,7 @@ Session::load_playlists (const XMLNode& node) { XMLNodeList nlist; XMLNodeConstIterator niter; - Playlist *playlist; + boost::shared_ptr<Playlist> playlist; nlist = node.children(); @@ -1702,7 +1704,7 @@ Session::load_unused_playlists (const XMLNode& node) { XMLNodeList nlist; XMLNodeConstIterator niter; - Playlist *playlist; + boost::shared_ptr<Playlist> playlist; nlist = node.children(); @@ -1717,22 +1719,22 @@ Session::load_unused_playlists (const XMLNode& node) // now manually untrack it - track_playlist (playlist, false); + track_playlist (false, boost::weak_ptr<Playlist> (playlist)); } return 0; } -Playlist * +boost::shared_ptr<Playlist> Session::XMLPlaylistFactory (const XMLNode& node) { try { - return new AudioPlaylist (*this, node); + return PlaylistFactory::create (*this, node); } catch (failed_constructor& err) { - return 0; + return boost::shared_ptr<Playlist>(); } } @@ -1792,7 +1794,6 @@ Session::sound_dir (bool with_path) const old_withpath = _path; old_withpath += old_sound_dir_name; - old_withpath += '/'; if (stat (old_withpath.c_str(), &statbuf) == 0) { if (with_path) @@ -1812,7 +1813,6 @@ Session::sound_dir (bool with_path) const res += legalize_for_path (_name); res += '/'; res += sound_dir_name; - res += '/'; return res; } @@ -2385,11 +2385,22 @@ Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_th return 0; } +struct RegionCounter { + typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList; + AudioSourceList::iterator iter; + boost::shared_ptr<Region> region; + uint32_t count; + + RegionCounter() : count (0) {} +}; + int Session::cleanup_sources (Session::cleanup_report& rep) { - vector<boost::shared_ptr<Source> > dead_sources; - vector<Playlist*> playlists_tbd; + typedef map<boost::shared_ptr<Source>, RegionCounter> SourceRegionMap; + SourceRegionMap dead_sources; + + vector<boost::shared_ptr<Playlist> > playlists_tbd; PathScanner scanner; string sound_path; vector<space_and_path>::iterator i; @@ -2428,74 +2439,114 @@ Session::cleanup_sources (Session::cleanup_report& rep) /* now delete any that were marked for deletion */ - for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) { - PlaylistList::iterator foo; - - if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) { - unused_playlists.erase (foo); - } - delete *x; + for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) { + (*x)->drop_references (); } + playlists_tbd.clear (); + /* step 2: find all un-referenced sources */ rep.paths.clear (); rep.space = 0; - for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) { - - AudioSourceList::iterator tmp; - - tmp = i; - ++tmp; + for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) { + + /* we expect the use_count() to be at least 2: one for the shared_ptr<> in the sources + list and one for the iterator. if its used by 1 region, we'd expect a value of 3. - /* only remove files that are not in use and have some size - to them. otherwise we remove the current "nascent" + do not bother with files that are zero size, otherwise we remove the current "nascent" capture files. */ - cerr << "checking out source " << i->second->name() << " use_count = " << i->second.use_count() << endl; + if (i->second.use_count() <= 3 && i->second->length() > 0) { - if (i->second.use_count() == 1 && i->second->length() > 0) { - dead_sources.push_back (i->second); + pair<boost::shared_ptr<Source>, RegionCounter> newpair; - /* remove this source from our own list to avoid us - adding it to the list of all sources below - */ - - audio_sources.erase (i); - } + newpair.first = i->second; + newpair.second.iter = i; - i = tmp; + dead_sources.insert (newpair); + } } - /* Step 3: get rid of all regions in the region list that use any dead sources - in case the sources themselves don't go away (they might be referenced in - other snapshots). - */ - - for (vector<boost::shared_ptr<Source> >::iterator i = dead_sources.begin(); i != dead_sources.end();++i) { + /* Search the region list to find out the state of the supposedly unreferenced regions + */ - for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) { - AudioRegionList::iterator tmp; - boost::shared_ptr<AudioRegion> ar; + for (SourceRegionMap::iterator i = dead_sources.begin(); i != dead_sources.end();++i) { - tmp = r; - ++tmp; + for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ++r) { - ar = r->second; + boost::shared_ptr<AudioRegion> ar = r->second; for (uint32_t n = 0; n < ar->n_channels(); ++n) { - if (ar->source (n) == (*i)) { - /* this region is dead */ - remove_region (ar); + + if (ar->source (n) == i->first) { + + /* this region uses this source */ + + i->second.region = ar; + i->second.count++; + + if (i->second.count > 1) { + break; + } } } - - r = tmp; } } + /* next, get rid of all regions in the region list that use any dead sources + in case the sources themselves don't go away (they might be referenced in + other snapshots). + + this is also where we remove the apparently unused sources from our source + list. this doesn't rename them or delete them, but it means they are + potential candidates for renaming after we find all soundfiles + and scan for use across all snapshots (including this one). + */ + + for (SourceRegionMap::iterator i = dead_sources.begin(); i != dead_sources.end(); ) { + + SourceRegionMap::iterator tmp; + + tmp = i; + ++tmp; + + if (i->second.count == 0) { + + /* no regions use this source */ + + /* remove this source from our own list to avoid us + adding it to the list of all sources below + */ + + audio_sources.erase (i->second.iter); + + } else if (i->second.count == 1) { + + /* the use_count for the source was 3. this means that there is only reference to it in addition to the source + list and an iterator used to traverse that list. since there is a single region using the source, that + must be the extra reference. this implies that its a whole-file region + with no children, so remove the region and the source. + */ + + remove_region (i->second.region); + + /* remove this source from our own list to avoid us + adding it to the list of all sources below + */ + + audio_sources.erase (i->second.iter); + + } else { + /* more than one region uses this source, do not remove it */ + dead_sources.erase (i); + } + + i = tmp; + } + /* build a list of all the possible sound directories for the session */ for (i = session_dirs.begin(); i != session_dirs.end(); ) { @@ -2504,7 +2555,7 @@ Session::cleanup_sources (Session::cleanup_report& rep) ++nexti; sound_path += (*i).path; - sound_path += sound_dir_name; + sound_path += sound_dir (false); if (nexti != session_dirs.end()) { sound_path += ':'; @@ -2512,7 +2563,7 @@ Session::cleanup_sources (Session::cleanup_report& rep) 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. */ @@ -2577,8 +2628,12 @@ Session::cleanup_sources (Session::cleanup_report& rep) on whichever filesystem it was already on. */ - newpath = Glib::path_get_dirname (*x); - newpath = Glib::path_get_dirname (newpath); + /* XXX this is a hack ... go up 4 levels */ + + newpath = Glib::path_get_dirname (*x); // "audiofiles" + newpath = Glib::path_get_dirname (newpath); // "session-name" + newpath = Glib::path_get_dirname (newpath); // "interchange" + newpath = Glib::path_get_dirname (newpath); // "session-dir" newpath += '/'; newpath += dead_sound_dir_name; @@ -2639,7 +2694,6 @@ Session::cleanup_sources (Session::cleanup_report& rep) goto out; } } - } ret = 0; |