mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
changes in logic used by source cleanup to avoid endless recursion in sessions with deeply nested/recursive compound regions.
This also fixes some potentially dangerous cleanup logic related to two sources with the same name (but different paths)
This commit is contained in:
parent
dbb26485df
commit
54d5f36311
8 changed files with 204 additions and 110 deletions
|
|
@ -130,7 +130,6 @@ public:
|
||||||
|
|
||||||
void add_region (boost::shared_ptr<Region>, framepos_t position, float times = 1, bool auto_partition = false);
|
void add_region (boost::shared_ptr<Region>, framepos_t position, float times = 1, bool auto_partition = false);
|
||||||
void remove_region (boost::shared_ptr<Region>);
|
void remove_region (boost::shared_ptr<Region>);
|
||||||
void remove_region_by_source (boost::shared_ptr<Source>);
|
|
||||||
void get_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
|
void get_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
|
||||||
void get_region_list_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
|
void get_region_list_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
|
||||||
void get_source_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
|
void get_source_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
|
||||||
|
|
@ -181,7 +180,8 @@ public:
|
||||||
bool region_is_shuffle_constrained (boost::shared_ptr<Region>);
|
bool region_is_shuffle_constrained (boost::shared_ptr<Region>);
|
||||||
bool has_region_at (framepos_t const) const;
|
bool has_region_at (framepos_t const) const;
|
||||||
|
|
||||||
bool uses_source (boost::shared_ptr<const Source> src) const;
|
bool uses_source (boost::shared_ptr<const Source> src, bool shallow = false) const;
|
||||||
|
void deep_sources (std::set<boost::shared_ptr<Source> >&) const;
|
||||||
|
|
||||||
framepos_t find_next_transient (framepos_t position, int dir);
|
framepos_t find_next_transient (framepos_t position, int dir);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,8 @@ class LIBARDOUR_API Region
|
||||||
bool region_list_equivalent (boost::shared_ptr<const Region>) const;
|
bool region_list_equivalent (boost::shared_ptr<const Region>) const;
|
||||||
bool source_equivalent (boost::shared_ptr<const Region>) const;
|
bool source_equivalent (boost::shared_ptr<const Region>) const;
|
||||||
bool any_source_equivalent (boost::shared_ptr<const Region>) const;
|
bool any_source_equivalent (boost::shared_ptr<const Region>) const;
|
||||||
bool uses_source (boost::shared_ptr<const Source>) const;
|
bool uses_source (boost::shared_ptr<const Source>, bool shallow = false) const;
|
||||||
|
void deep_sources (std::set<boost::shared_ptr<Source> >&) const;
|
||||||
|
|
||||||
std::string source_string () const;
|
std::string source_string () const;
|
||||||
|
|
||||||
|
|
@ -310,7 +311,7 @@ class LIBARDOUR_API Region
|
||||||
/** merges _onsets OR _transients with _user_transients into given list
|
/** merges _onsets OR _transients with _user_transients into given list
|
||||||
* if _onsets and _transients are unset, run analysis.
|
* if _onsets and _transients are unset, run analysis.
|
||||||
* list is not thinned, duplicates remain in place.
|
* list is not thinned, duplicates remain in place.
|
||||||
*
|
*
|
||||||
* intended for: Playlist::find_next_transient ()
|
* intended for: Playlist::find_next_transient ()
|
||||||
*/
|
*/
|
||||||
virtual void get_transients (AnalysisFeatureList&) {
|
virtual void get_transients (AnalysisFeatureList&) {
|
||||||
|
|
|
||||||
|
|
@ -54,12 +54,14 @@ public:
|
||||||
uint32_t source_use_count (boost::shared_ptr<const Source> src) const;
|
uint32_t source_use_count (boost::shared_ptr<const Source> src) const;
|
||||||
uint32_t region_use_count (boost::shared_ptr<Region> region) const;
|
uint32_t region_use_count (boost::shared_ptr<Region> region) const;
|
||||||
template<class T> void foreach (T *obj, void (T::*func)(boost::shared_ptr<Playlist>));
|
template<class T> void foreach (T *obj, void (T::*func)(boost::shared_ptr<Playlist>));
|
||||||
|
void foreach (boost::function<void(boost::shared_ptr<const Playlist>)> functor);
|
||||||
void get (std::vector<boost::shared_ptr<Playlist> >&) const;
|
void get (std::vector<boost::shared_ptr<Playlist> >&) const;
|
||||||
void unassigned (std::list<boost::shared_ptr<Playlist> > & list);
|
void unassigned (std::list<boost::shared_ptr<Playlist> > & list);
|
||||||
void destroy_region (boost::shared_ptr<Region>);
|
void destroy_region (boost::shared_ptr<Region>);
|
||||||
boost::shared_ptr<Crossfade> find_crossfade (const PBD::ID &);
|
boost::shared_ptr<Crossfade> find_crossfade (const PBD::ID &);
|
||||||
void sync_all_regions_with_regions ();
|
void sync_all_regions_with_regions ();
|
||||||
std::vector<boost::shared_ptr<Playlist> > playlists_for_track (boost::shared_ptr<Track>) const;
|
std::vector<boost::shared_ptr<Playlist> > playlists_for_track (boost::shared_ptr<Track>) const;
|
||||||
|
uint32_t n_playlists() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Session;
|
friend class Session;
|
||||||
|
|
@ -69,7 +71,6 @@ private:
|
||||||
void remove_weak (boost::weak_ptr<Playlist>);
|
void remove_weak (boost::weak_ptr<Playlist>);
|
||||||
void track (bool, boost::weak_ptr<Playlist>);
|
void track (bool, boost::weak_ptr<Playlist>);
|
||||||
|
|
||||||
uint32_t n_playlists() const;
|
|
||||||
void find_equivalent_playlist_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >& result);
|
void find_equivalent_playlist_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >& result);
|
||||||
void update_after_tempo_map_change ();
|
void update_after_tempo_map_change ();
|
||||||
void add_state (XMLNode *, bool);
|
void add_state (XMLNode *, bool);
|
||||||
|
|
|
||||||
|
|
@ -1774,12 +1774,23 @@ Playlist::region_bounds_changed (const PropertyChange& what_changed, boost::shar
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
boost::shared_ptr<RegionList>
|
boost::shared_ptr<RegionList>
|
||||||
Playlist::region_list() {
|
Playlist::region_list()
|
||||||
|
{
|
||||||
RegionReadLock rlock (this);
|
RegionReadLock rlock (this);
|
||||||
boost::shared_ptr<RegionList> rlist (new RegionList (regions.rlist ()));
|
boost::shared_ptr<RegionList> rlist (new RegionList (regions.rlist ()));
|
||||||
return rlist;
|
return rlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Playlist::deep_sources (std::set<boost::shared_ptr<Source> >& sources) const
|
||||||
|
{
|
||||||
|
RegionReadLock rlock (const_cast<Playlist*>(this));
|
||||||
|
|
||||||
|
for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||||
|
(*i)->deep_sources (sources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boost::shared_ptr<RegionList>
|
boost::shared_ptr<RegionList>
|
||||||
Playlist::regions_at (framepos_t frame)
|
Playlist::regions_at (framepos_t frame)
|
||||||
{
|
{
|
||||||
|
|
@ -2659,12 +2670,12 @@ Playlist::nudge_after (framepos_t start, framecnt_t distance, bool forwards)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Playlist::uses_source (boost::shared_ptr<const Source> src) const
|
Playlist::uses_source (boost::shared_ptr<const Source> src, bool shallow) const
|
||||||
{
|
{
|
||||||
RegionReadLock rlock (const_cast<Playlist*> (this));
|
RegionReadLock rlock (const_cast<Playlist*> (this));
|
||||||
|
|
||||||
for (set<boost::shared_ptr<Region> >::const_iterator r = all_regions.begin(); r != all_regions.end(); ++r) {
|
for (set<boost::shared_ptr<Region> >::const_iterator r = all_regions.begin(); r != all_regions.end(); ++r) {
|
||||||
if ((*r)->uses_source (src)) {
|
if ((*r)->uses_source (src, true)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2672,6 +2683,7 @@ Playlist::uses_source (boost::shared_ptr<const Source> src) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boost::shared_ptr<Region>
|
boost::shared_ptr<Region>
|
||||||
Playlist::find_region (const ID& id) const
|
Playlist::find_region (const ID& id) const
|
||||||
{
|
{
|
||||||
|
|
@ -2936,25 +2948,6 @@ Playlist::has_region_at (framepos_t const p) const
|
||||||
return (i != regions.end());
|
return (i != regions.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Remove any region that uses a given source */
|
|
||||||
void
|
|
||||||
Playlist::remove_region_by_source (boost::shared_ptr<Source> s)
|
|
||||||
{
|
|
||||||
RegionWriteLock rl (this);
|
|
||||||
|
|
||||||
RegionList::iterator i = regions.begin();
|
|
||||||
while (i != regions.end()) {
|
|
||||||
RegionList::iterator j = i;
|
|
||||||
++j;
|
|
||||||
|
|
||||||
if ((*i)->uses_source (s)) {
|
|
||||||
remove_region_internal (*i);
|
|
||||||
}
|
|
||||||
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Look from a session frame time and find the start time of the next region
|
/** Look from a session frame time and find the start time of the next region
|
||||||
* which is on the top layer of this playlist.
|
* which is on the top layer of this playlist.
|
||||||
* @param t Time to look from.
|
* @param t Time to look from.
|
||||||
|
|
|
||||||
|
|
@ -81,55 +81,55 @@ void
|
||||||
Region::make_property_quarks ()
|
Region::make_property_quarks ()
|
||||||
{
|
{
|
||||||
Properties::muted.property_id = g_quark_from_static_string (X_("muted"));
|
Properties::muted.property_id = g_quark_from_static_string (X_("muted"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for muted = %1\n", Properties::muted.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for muted = %1\n", Properties::muted.property_id));
|
||||||
Properties::opaque.property_id = g_quark_from_static_string (X_("opaque"));
|
Properties::opaque.property_id = g_quark_from_static_string (X_("opaque"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for opaque = %1\n", Properties::opaque.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for opaque = %1\n", Properties::opaque.property_id));
|
||||||
Properties::locked.property_id = g_quark_from_static_string (X_("locked"));
|
Properties::locked.property_id = g_quark_from_static_string (X_("locked"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for locked = %1\n", Properties::locked.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for locked = %1\n", Properties::locked.property_id));
|
||||||
Properties::video_locked.property_id = g_quark_from_static_string (X_("video-locked"));
|
Properties::video_locked.property_id = g_quark_from_static_string (X_("video-locked"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for video-locked = %1\n", Properties::video_locked.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for video-locked = %1\n", Properties::video_locked.property_id));
|
||||||
Properties::automatic.property_id = g_quark_from_static_string (X_("automatic"));
|
Properties::automatic.property_id = g_quark_from_static_string (X_("automatic"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for automatic = %1\n", Properties::automatic.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for automatic = %1\n", Properties::automatic.property_id));
|
||||||
Properties::whole_file.property_id = g_quark_from_static_string (X_("whole-file"));
|
Properties::whole_file.property_id = g_quark_from_static_string (X_("whole-file"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for whole-file = %1\n", Properties::whole_file.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for whole-file = %1\n", Properties::whole_file.property_id));
|
||||||
Properties::import.property_id = g_quark_from_static_string (X_("import"));
|
Properties::import.property_id = g_quark_from_static_string (X_("import"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for import = %1\n", Properties::import.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for import = %1\n", Properties::import.property_id));
|
||||||
Properties::external.property_id = g_quark_from_static_string (X_("external"));
|
Properties::external.property_id = g_quark_from_static_string (X_("external"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for external = %1\n", Properties::external.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for external = %1\n", Properties::external.property_id));
|
||||||
Properties::sync_marked.property_id = g_quark_from_static_string (X_("sync-marked"));
|
Properties::sync_marked.property_id = g_quark_from_static_string (X_("sync-marked"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for sync-marked = %1\n", Properties::sync_marked.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for sync-marked = %1\n", Properties::sync_marked.property_id));
|
||||||
Properties::left_of_split.property_id = g_quark_from_static_string (X_("left-of-split"));
|
Properties::left_of_split.property_id = g_quark_from_static_string (X_("left-of-split"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for left-of-split = %1\n", Properties::left_of_split.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for left-of-split = %1\n", Properties::left_of_split.property_id));
|
||||||
Properties::right_of_split.property_id = g_quark_from_static_string (X_("right-of-split"));
|
Properties::right_of_split.property_id = g_quark_from_static_string (X_("right-of-split"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for right-of-split = %1\n", Properties::right_of_split.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for right-of-split = %1\n", Properties::right_of_split.property_id));
|
||||||
Properties::hidden.property_id = g_quark_from_static_string (X_("hidden"));
|
Properties::hidden.property_id = g_quark_from_static_string (X_("hidden"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for hidden = %1\n", Properties::hidden.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for hidden = %1\n", Properties::hidden.property_id));
|
||||||
Properties::position_locked.property_id = g_quark_from_static_string (X_("position-locked"));
|
Properties::position_locked.property_id = g_quark_from_static_string (X_("position-locked"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position-locked = %1\n", Properties::position_locked.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position-locked = %1\n", Properties::position_locked.property_id));
|
||||||
Properties::valid_transients.property_id = g_quark_from_static_string (X_("valid-transients"));
|
Properties::valid_transients.property_id = g_quark_from_static_string (X_("valid-transients"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for valid-transients = %1\n", Properties::valid_transients.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for valid-transients = %1\n", Properties::valid_transients.property_id));
|
||||||
Properties::start.property_id = g_quark_from_static_string (X_("start"));
|
Properties::start.property_id = g_quark_from_static_string (X_("start"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for start = %1\n", Properties::start.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for start = %1\n", Properties::start.property_id));
|
||||||
Properties::length.property_id = g_quark_from_static_string (X_("length"));
|
Properties::length.property_id = g_quark_from_static_string (X_("length"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for length = %1\n", Properties::length.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for length = %1\n", Properties::length.property_id));
|
||||||
Properties::position.property_id = g_quark_from_static_string (X_("position"));
|
Properties::position.property_id = g_quark_from_static_string (X_("position"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position = %1\n", Properties::position.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position = %1\n", Properties::position.property_id));
|
||||||
Properties::sync_position.property_id = g_quark_from_static_string (X_("sync-position"));
|
Properties::sync_position.property_id = g_quark_from_static_string (X_("sync-position"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for sync-position = %1\n", Properties::sync_position.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for sync-position = %1\n", Properties::sync_position.property_id));
|
||||||
Properties::layer.property_id = g_quark_from_static_string (X_("layer"));
|
Properties::layer.property_id = g_quark_from_static_string (X_("layer"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layer = %1\n", Properties::layer.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layer = %1\n", Properties::layer.property_id));
|
||||||
Properties::ancestral_start.property_id = g_quark_from_static_string (X_("ancestral-start"));
|
Properties::ancestral_start.property_id = g_quark_from_static_string (X_("ancestral-start"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for ancestral-start = %1\n", Properties::ancestral_start.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for ancestral-start = %1\n", Properties::ancestral_start.property_id));
|
||||||
Properties::ancestral_length.property_id = g_quark_from_static_string (X_("ancestral-length"));
|
Properties::ancestral_length.property_id = g_quark_from_static_string (X_("ancestral-length"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for ancestral-length = %1\n", Properties::ancestral_length.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for ancestral-length = %1\n", Properties::ancestral_length.property_id));
|
||||||
Properties::stretch.property_id = g_quark_from_static_string (X_("stretch"));
|
Properties::stretch.property_id = g_quark_from_static_string (X_("stretch"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for stretch = %1\n", Properties::stretch.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for stretch = %1\n", Properties::stretch.property_id));
|
||||||
Properties::shift.property_id = g_quark_from_static_string (X_("shift"));
|
Properties::shift.property_id = g_quark_from_static_string (X_("shift"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for shift = %1\n", Properties::shift.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for shift = %1\n", Properties::shift.property_id));
|
||||||
Properties::position_lock_style.property_id = g_quark_from_static_string (X_("positional-lock-style"));
|
Properties::position_lock_style.property_id = g_quark_from_static_string (X_("positional-lock-style"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position_lock_style = %1\n", Properties::position_lock_style.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position_lock_style = %1\n", Properties::position_lock_style.property_id));
|
||||||
Properties::layering_index.property_id = g_quark_from_static_string (X_("layering-index"));
|
Properties::layering_index.property_id = g_quark_from_static_string (X_("layering-index"));
|
||||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layering_index = %1\n", Properties::layering_index.property_id));
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layering_index = %1\n", Properties::layering_index.property_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1522,19 +1522,59 @@ Region::source_string () const
|
||||||
return res.str();
|
return res.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Region::deep_sources (std::set<boost::shared_ptr<Source> > & sources) const
|
||||||
|
{
|
||||||
|
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
|
||||||
|
|
||||||
|
boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
|
||||||
|
|
||||||
|
if (ps) {
|
||||||
|
if (sources.find (ps) == sources.end()) {
|
||||||
|
ps->playlist()->deep_sources (sources);
|
||||||
|
cerr << ps->name() << " new source\n";
|
||||||
|
} else {
|
||||||
|
cerr << ps->name() << " already in source list\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sources.insert (*i);
|
||||||
|
cerr << "Added src " << (*i)->name() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SourceList::const_iterator i = _master_sources.begin(); i != _master_sources.end(); ++i) {
|
||||||
|
|
||||||
|
boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
|
||||||
|
|
||||||
|
if (ps) {
|
||||||
|
if (sources.find (ps) == sources.end()) {
|
||||||
|
ps->playlist()->deep_sources (sources);
|
||||||
|
cerr << ps->name() << " new source2\n";
|
||||||
|
} else {
|
||||||
|
cerr << ps->name() << " already in source list2\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sources.insert (*i);
|
||||||
|
cerr << "Added master src " << (*i)->name() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Region::uses_source (boost::shared_ptr<const Source> source) const
|
Region::uses_source (boost::shared_ptr<const Source> source, bool shallow) const
|
||||||
{
|
{
|
||||||
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
|
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
|
||||||
if (*i == source) {
|
if (*i == source) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
|
if (!shallow) {
|
||||||
|
boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
|
||||||
|
|
||||||
if (ps) {
|
if (ps) {
|
||||||
if (ps->playlist()->uses_source (source)) {
|
if (ps->playlist()->uses_source (source)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1544,11 +1584,13 @@ Region::uses_source (boost::shared_ptr<const Source> source) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
|
if (!shallow) {
|
||||||
|
boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
|
||||||
|
|
||||||
if (ps) {
|
if (ps) {
|
||||||
if (ps->playlist()->uses_source (source)) {
|
if (ps->playlist()->uses_source (source)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1556,6 +1598,7 @@ Region::uses_source (boost::shared_ptr<const Source> source) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
framecnt_t
|
framecnt_t
|
||||||
Region::source_length(uint32_t n) const
|
Region::source_length(uint32_t n) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -636,7 +636,7 @@ RegionFactory::get_regions_using_source (boost::shared_ptr<Source> s, std::set<b
|
||||||
{
|
{
|
||||||
Glib::Threads::Mutex::Lock lm (region_map_lock);
|
Glib::Threads::Mutex::Lock lm (region_map_lock);
|
||||||
|
|
||||||
for (RegionMap::iterator i = region_map.begin(); i != region_map.end(); ++i) {
|
for (RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
|
||||||
if (i->second->uses_source (s)) {
|
if (i->second->uses_source (s)) {
|
||||||
r.insert (i->second);
|
r.insert (i->second);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,7 @@ SessionPlaylists::source_use_count (boost::shared_ptr<const Source> src) const
|
||||||
{
|
{
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
cerr << "\t\tcheck " << playlists.size() << " playlists\n";
|
||||||
for (List::const_iterator p = playlists.begin(); p != playlists.end(); ++p) {
|
for (List::const_iterator p = playlists.begin(); p != playlists.end(); ++p) {
|
||||||
if ((*p)->uses_source (src)) {
|
if ((*p)->uses_source (src)) {
|
||||||
++count;
|
++count;
|
||||||
|
|
@ -267,6 +268,7 @@ SessionPlaylists::source_use_count (boost::shared_ptr<const Source> src) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "\t\tcheck " << playlists.size() << " unused playlists\n";
|
||||||
for (List::const_iterator p = unused_playlists.begin(); p != unused_playlists.end(); ++p) {
|
for (List::const_iterator p = unused_playlists.begin(); p != unused_playlists.end(); ++p) {
|
||||||
if ((*p)->uses_source (src)) {
|
if ((*p)->uses_source (src)) {
|
||||||
++count;
|
++count;
|
||||||
|
|
@ -500,3 +502,20 @@ SessionPlaylists::playlists_for_track (boost::shared_ptr<Track> tr) const
|
||||||
|
|
||||||
return pl_tr;
|
return pl_tr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SessionPlaylists::foreach (boost::function<void(boost::shared_ptr<const Playlist>)> functor)
|
||||||
|
{
|
||||||
|
Glib::Threads::Mutex::Lock lm (lock);
|
||||||
|
for (List::iterator i = playlists.begin(); i != playlists.end(); i++) {
|
||||||
|
if (!(*i)->hidden()) {
|
||||||
|
functor (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (List::iterator i = unused_playlists.begin(); i != unused_playlists.end(); i++) {
|
||||||
|
if (!(*i)->hidden()) {
|
||||||
|
functor (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2872,14 +2872,17 @@ Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_th
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this_snapshot_path = _path;
|
this_snapshot_path = Glib::build_filename (_path, legalize_for_path (_current_snapshot_name));
|
||||||
this_snapshot_path += legalize_for_path (_current_snapshot_name);
|
|
||||||
this_snapshot_path += statefile_suffix;
|
this_snapshot_path += statefile_suffix;
|
||||||
|
|
||||||
for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
|
for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
|
||||||
|
|
||||||
|
cerr << "Looking at snapshot " << (*i) << " ( with this = [" << this_snapshot_path << "])\n";
|
||||||
|
|
||||||
if (exclude_this_snapshot && *i == this_snapshot_path) {
|
if (exclude_this_snapshot && *i == this_snapshot_path) {
|
||||||
|
cerr << "\texcluded\n";
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (find_all_sources (*i, result) < 0) {
|
if (find_all_sources (*i, result) < 0) {
|
||||||
|
|
@ -3010,6 +3013,12 @@ Session::cleanup_peakfiles ()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
merge_all_sources (boost::shared_ptr<const Playlist> pl, std::set<boost::shared_ptr<Source> >* all_sources)
|
||||||
|
{
|
||||||
|
pl->deep_sources (*all_sources);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Session::cleanup_sources (CleanupReport& rep)
|
Session::cleanup_sources (CleanupReport& rep)
|
||||||
{
|
{
|
||||||
|
|
@ -3020,14 +3029,14 @@ Session::cleanup_sources (CleanupReport& rep)
|
||||||
string midi_path;
|
string midi_path;
|
||||||
vector<string> candidates;
|
vector<string> candidates;
|
||||||
vector<string> unused;
|
vector<string> unused;
|
||||||
set<string> all_sources;
|
set<string> sources_used_by_all_snapshots;
|
||||||
bool used;
|
|
||||||
string spath;
|
string spath;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
string tmppath1;
|
string tmppath1;
|
||||||
string tmppath2;
|
string tmppath2;
|
||||||
Searchpath asp;
|
Searchpath asp;
|
||||||
Searchpath msp;
|
Searchpath msp;
|
||||||
|
set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
|
||||||
|
|
||||||
_state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
|
_state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
|
||||||
|
|
||||||
|
|
@ -3098,12 +3107,21 @@ Session::cleanup_sources (CleanupReport& rep)
|
||||||
find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
|
find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
|
||||||
find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
|
find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
|
||||||
|
|
||||||
/* find all sources, but don't use this snapshot because the
|
/* add sources from all other snapshots as "used", but don't use this
|
||||||
state file on disk still references sources we may have already
|
snapshot because the state file on disk still references sources we
|
||||||
dropped.
|
may have already dropped.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
find_all_sources_across_snapshots (all_sources, true);
|
find_all_sources_across_snapshots (sources_used_by_all_snapshots, true);
|
||||||
|
|
||||||
|
/* Although the region factory has a list of all regions ever created
|
||||||
|
* for this session, we're only interested in regions actually in
|
||||||
|
* playlists right now. So merge all playlist regions lists together.
|
||||||
|
*
|
||||||
|
* This will include the playlists used within compound regions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot));
|
||||||
|
|
||||||
/* add our current source list
|
/* add our current source list
|
||||||
*/
|
*/
|
||||||
|
|
@ -3113,59 +3131,76 @@ Session::cleanup_sources (CleanupReport& rep)
|
||||||
SourceMap::iterator tmp = i;
|
SourceMap::iterator tmp = i;
|
||||||
++tmp;
|
++tmp;
|
||||||
|
|
||||||
if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
|
if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) == 0) {
|
||||||
|
/* not a file */
|
||||||
|
i = tmp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* this is mostly for windows which doesn't allow file
|
/* this is mostly for windows which doesn't allow file
|
||||||
* renaming if the file is in use. But we don't special
|
* renaming if the file is in use. But we do not special
|
||||||
* case it because we need to know if this causes
|
* case it because we need to know if this causes
|
||||||
* problems, and the easiest way to notice that is to
|
* problems, and the easiest way to notice that is to
|
||||||
* keep it in place for all platforms.
|
* keep it in place for all platforms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fs->close ();
|
||||||
|
|
||||||
|
if (!fs->is_stub()) {
|
||||||
|
|
||||||
|
/* Note that we're checking a list of all
|
||||||
|
* sources across all snapshots with the list
|
||||||
|
* of sources used by this snapshot.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fs->close ();
|
if (sources_used_by_this_snapshot.find (i->second) != sources_used_by_this_snapshot.end()) {
|
||||||
|
/* this source is in use by this snapshot */
|
||||||
|
sources_used_by_all_snapshots.insert (fs->path());
|
||||||
|
cerr << "Source from source list found in used_by_this_snapshot (" << fs->path() << ")\n";
|
||||||
|
} else {
|
||||||
|
cerr << "Source from source list NOT found in used_by_this_snapshot (" << fs->path() << ")\n";
|
||||||
|
/* this source is NOT in use by this snapshot
|
||||||
|
*/
|
||||||
|
|
||||||
if (!fs->is_stub()) {
|
/* remove all related regions from RegionFactory master list
|
||||||
|
*/
|
||||||
|
|
||||||
if (playlists->source_use_count (fs) != 0) {
|
RegionFactory::remove_regions_using_source (i->second);
|
||||||
all_sources.insert (fs->path());
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* we might not remove this source from disk, because it may be used
|
/* remove from our current source list
|
||||||
by other snapshots, but its not being used in this version
|
* also. We may not remove it from
|
||||||
so lets get rid of it now, along with any representative regions
|
* disk, because it may be used by
|
||||||
in the region list.
|
* other snapshots, but it isn't used inside this
|
||||||
*/
|
* snapshot anymore, so we don't need a
|
||||||
|
* reference to it.
|
||||||
|
*/
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sources.erase (i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i = tmp;
|
i = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* now check each candidate source to see if it exists in the list of
|
||||||
|
sources_used_by_all_snapshots. If it doesn't, put it into "unused".
|
||||||
|
*/
|
||||||
|
|
||||||
|
cerr << "Candidates: " << candidates.size() << endl;
|
||||||
|
cerr << "Used by others: " << sources_used_by_all_snapshots.size() << endl;
|
||||||
|
|
||||||
for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
|
for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
|
||||||
|
|
||||||
used = false;
|
bool used = false;
|
||||||
spath = *x;
|
spath = *x;
|
||||||
|
|
||||||
for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
|
for (set<string>::iterator i = sources_used_by_all_snapshots.begin(); i != sources_used_by_all_snapshots.end(); ++i) {
|
||||||
|
|
||||||
tmppath1 = canonical_path (spath);
|
tmppath1 = canonical_path (spath);
|
||||||
tmppath2 = canonical_path ((*i));
|
tmppath2 = canonical_path ((*i));
|
||||||
|
|
||||||
|
cerr << "\t => " << tmppath2 << endl;
|
||||||
|
|
||||||
if (tmppath1 == tmppath2) {
|
if (tmppath1 == tmppath2) {
|
||||||
used = true;
|
used = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -3177,6 +3212,14 @@ Session::cleanup_sources (CleanupReport& rep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cerr << "Actually unused: " << unused.size() << endl;
|
||||||
|
|
||||||
|
if (unused.empty()) {
|
||||||
|
/* Nothing to do */
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* now try to move all unused files into the "dead" 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) {
|
for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
|
||||||
|
|
@ -3239,19 +3282,13 @@ Session::cleanup_sources (CleanupReport& rep)
|
||||||
newpath = newpath_v;
|
newpath = newpath_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* it doesn't exist, or we can't read it or something */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_stat ((*x).c_str(), &statbuf);
|
g_stat ((*x).c_str(), &statbuf);
|
||||||
|
|
||||||
if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
|
if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
|
||||||
error << string_compose (_("cannot rename unused 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;
|
||||||
(*x), newpath, strerror (errno))
|
continue;
|
||||||
<< endmsg;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see if there an easy to find peakfile for this file, and remove it.
|
/* see if there an easy to find peakfile for this file, and remove it.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue