+
+void
+Region::source_deleted (boost::weak_ptr<Source>)
+{
+ drop_sources ();
+
+ if (!_session.deletion_in_progress()) {
+ /* this is a very special case: at least one of the region's
+ sources has bee deleted, so invalidate all references to
+ ourselves. Do NOT do this during session deletion, because
+ then we run the risk that this will actually result
+ in this object being deleted (as refcnt goes to zero)
+ while emitting DropReferences.
+ */
+
+ drop_references ();
+ }
+}
+
+vector<string>
+Region::master_source_names ()
+{
+ SourceList::iterator i;
+
+ vector<string> names;
+ for (i = _master_sources.begin(); i != _master_sources.end(); ++i) {
+ names.push_back((*i)->name());
+ }
+
+ return names;
+}
+
+void
+Region::set_master_sources (const SourceList& srcs)
+{
+ for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
+ (*i)->dec_use_count ();
+ }
+
+ _master_sources = srcs;
+ assert (_sources.size() == _master_sources.size());
+
+ for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
+ (*i)->inc_use_count ();
+ }
+}
+
+bool
+Region::source_equivalent (boost::shared_ptr<const Region> other) const
+{
+ if (!other)
+ return false;
+
+ if ((_sources.size() != other->_sources.size()) ||
+ (_master_sources.size() != other->_master_sources.size())) {
+ return false;
+ }
+
+ SourceList::const_iterator i;
+ SourceList::const_iterator io;
+
+ for (i = _sources.begin(), io = other->_sources.begin(); i != _sources.end() && io != other->_sources.end(); ++i, ++io) {
+ if ((*i)->id() != (*io)->id()) {
+ return false;
+ }
+ }
+
+ for (i = _master_sources.begin(), io = other->_master_sources.begin(); i != _master_sources.end() && io != other->_master_sources.end(); ++i, ++io) {
+ if ((*i)->id() != (*io)->id()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+Region::uses_source (boost::shared_ptr<const Source> source) const
+{
+ for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
+ if (*i == source) {
+ return true;
+ }
+ }
+ return false;
+}
+
+sframes_t
+Region::source_length(uint32_t n) const
+{
+ assert (n < _sources.size());
+ return _sources[n]->length(_position - _start);
+}
+
+bool
+Region::verify_length (framecnt_t len)
+{
+ if (source() && (source()->destructive() || source()->length_mutable())) {
+ return true;
+ }
+
+ framecnt_t maxlen = 0;
+
+ for (uint32_t n = 0; n < _sources.size(); ++n) {
+ maxlen = max (maxlen, source_length(n) - _start);
+ }
+
+ len = min (len, maxlen);
+
+ return true;
+}
+
+bool
+Region::verify_start_and_length (framepos_t new_start, framecnt_t& new_length)
+{
+ if (source() && (source()->destructive() || source()->length_mutable())) {
+ return true;
+ }
+
+ framecnt_t maxlen = 0;
+
+ for (uint32_t n = 0; n < _sources.size(); ++n) {
+ maxlen = max (maxlen, source_length(n) - new_start);
+ }
+
+ new_length = min (new_length, maxlen);
+
+ return true;
+}
+
+bool
+Region::verify_start (framepos_t pos)
+{
+ if (source() && (source()->destructive() || source()->length_mutable())) {
+ return true;
+ }
+
+ for (uint32_t n = 0; n < _sources.size(); ++n) {
+ if (pos > source_length(n) - _length) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+Region::verify_start_mutable (framepos_t& new_start)
+{
+ if (source() && (source()->destructive() || source()->length_mutable())) {
+ return true;
+ }
+
+ for (uint32_t n = 0; n < _sources.size(); ++n) {
+ if (new_start > source_length(n) - _length) {
+ new_start = source_length(n) - _length;
+ }
+ }
+ return true;
+}
+
+boost::shared_ptr<Region>
+Region::get_parent() const
+{
+ boost::shared_ptr<Playlist> pl (playlist());
+
+ if (pl) {
+ boost::shared_ptr<Region> r;
+ boost::shared_ptr<Region const> grrr2 = boost::dynamic_pointer_cast<Region const> (shared_from_this());
+
+ if (grrr2 && (r = _session.find_whole_file_parent (grrr2))) {
+ return boost::static_pointer_cast<Region> (r);
+ }
+ }
+
+ return boost::shared_ptr<Region>();
+}
+
+int
+Region::apply (Filter& filter)
+{
+ return filter.run (shared_from_this());
+}
+
+
+void
+Region::invalidate_transients ()
+{
+ _valid_transients = false;
+ _transients.clear ();
+
+ send_change (PropertyChange (Properties::valid_transients));
+}
+
+void
+Region::drop_sources ()
+{
+ for (SourceList::const_iterator i = _sources.begin (); i != _sources.end(); ++i) {
+ (*i)->dec_use_count ();
+ }
+
+ _sources.clear ();
+
+ for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
+ (*i)->dec_use_count ();
+ }
+
+ _master_sources.clear ();
+}
+
+void
+Region::use_sources (SourceList const & s)
+{
+ set<boost::shared_ptr<Source> > unique_srcs;
+
+ for (SourceList::const_iterator i = s.begin (); i != s.end(); ++i) {
+
+ _sources.push_back (*i);
+ (*i)->inc_use_count ();
+ _master_sources.push_back (*i);
+ (*i)->inc_use_count ();
+
+ /* connect only once to DropReferences, even if sources are replicated
+ */
+
+ if (unique_srcs.find (*i) == unique_srcs.end ()) {
+ unique_srcs.insert (*i);
+ (*i)->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr<Source>(*i)));
+ }
+ }
+}