X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fregion.cc;h=1f4d6f0f912221d78d3fc4739ea8840a82d13af4;hb=7d96960b162d25da87c388a3083775e8770bba56;hp=19f26966a70e95bbe39f7caecc058be501a37f80;hpb=ec222cc4299dcc75a12925e76fa897a543539301;p=ardour.git diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 19f26966a7..1f4d6f0f91 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2003 Paul Davis + Copyright (C) 2000-2003 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,14 +23,13 @@ #include #include -#include -#include #include #include "pbd/xml++.h" #include "pbd/stacktrace.h" #include "pbd/enumwriter.h" +#include "ardour/debug.h" #include "ardour/region.h" #include "ardour/playlist.h" #include "ardour/session.h" @@ -55,17 +54,17 @@ Change Region::LockChanged = ARDOUR::new_change (); Change Region::LayerChanged = ARDOUR::new_change (); Change Region::HiddenChanged = ARDOUR::new_change (); -sigc::signal > Region::RegionPropertyChanged; +PBD::Signal1 > Region::RegionPropertyChanged; /* derived-from-derived constructor (no sources in constructor) */ Region::Region (Session& s, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags) : SessionObject(s, name) , _type(type) - , _flags(flags) - , _start(start) - , _length(length) - , _position(0) - , _last_position(0) + , _flags(Flag (flags|DoNotSendPropertyChanges)) + , _start(start) + , _length(length) + , _position(0) + , _last_position(0) , _positional_lock_style(AudioTime) , _sync_position(_start) , _layer(layer) @@ -78,6 +77,7 @@ Region::Region (Session& s, nframes_t start, nframes_t length, const string& nam , _read_data_count(0) , _pending_changed(Change (0)) , _last_layer_op(0) + , _pending_explicit_relayer (false) { /* no sources at this point */ } @@ -86,11 +86,11 @@ Region::Region (Session& s, nframes_t start, nframes_t length, const string& nam Region::Region (boost::shared_ptr src, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags) : SessionObject(src->session(), name) , _type(type) - , _flags(flags) - , _start(start) - , _length(length) - , _position(0) - , _last_position(0) + , _flags(Flag (flags|DoNotSendPropertyChanges)) + , _start(start) + , _length(length) + , _position(0) + , _last_position(0) , _positional_lock_style(AudioTime) , _sync_position(_start) , _layer(layer) @@ -104,12 +104,12 @@ Region::Region (boost::shared_ptr src, nframes_t start, nframes_t length , _read_data_count(0) , _pending_changed(Change (0)) , _last_layer_op(0) - + , _pending_explicit_relayer (false) { _sources.push_back (src); _master_sources.push_back (src); - src->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), src)); + src->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr(src))); assert(_sources.size() > 0); _positional_lock_style = AudioTime; @@ -119,11 +119,11 @@ Region::Region (boost::shared_ptr src, nframes_t start, nframes_t length Region::Region (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, DataType type, layer_t layer, Region::Flag flags) : SessionObject(srcs.front()->session(), name) , _type(type) - , _flags(flags) - , _start(start) - , _length(length) - , _position(0) - , _last_position(0) + , _flags(Flag (flags|DoNotSendPropertyChanges)) + , _start(start) + , _length(length) + , _position(0) + , _last_position(0) , _positional_lock_style(AudioTime) , _sync_position(_start) , _layer(layer) @@ -136,6 +136,7 @@ Region::Region (const SourceList& srcs, nframes_t start, nframes_t length, const , _read_data_count(0) , _pending_changed(Change (0)) , _last_layer_op(0) + , _pending_explicit_relayer (false) { use_sources (srcs); assert(_sources.size() > 0); @@ -145,11 +146,14 @@ Region::Region (const SourceList& srcs, nframes_t start, nframes_t length, const Region::Region (boost::shared_ptr other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags) : SessionObject(other->session(), name) , _type (other->data_type()) + , _pending_explicit_relayer (false) { _start = other->_start + offset; copy_stuff (other, offset, length, name, layer, flags); + _flags = Flag (_flags | DoNotSendPropertyChanges); + /* if the other region had a distinct sync point set, then continue to use it as best we can. otherwise, reset sync point back to start. @@ -182,23 +186,26 @@ Region::Region (boost::shared_ptr other, nframes_t offset, nframes Region::Region (boost::shared_ptr other, nframes_t length, const string& name, layer_t layer, Flag flags) : SessionObject(other->session(), name) , _type (other->data_type()) + , _pending_explicit_relayer (false) { /* create a new Region exactly like another but starting at 0 in its sources */ _start = 0; copy_stuff (other, 0, length, name, layer, flags); + _flags = Flag (_flags | DoNotSendPropertyChanges); + /* sync pos is relative to start of file. our start-in-file is now zero, so set our sync position to whatever the the difference between - _start and _sync_pos was in the other region. + _start and _sync_pos was in the other region. - result is that our new sync pos points to the same point in our source(s) + result is that our new sync pos points to the same point in our source(s) as the sync in the other region did in its source(s). since we start at zero in our source(s), it is not possible to use a sync point that is before the start. reset it to _start if that was true in the other region. */ - + if (other->flags() & SyncMarked) { if (other->_start < other->_sync_position) { /* sync pos was after the start point of the other region */ @@ -212,7 +219,7 @@ Region::Region (boost::shared_ptr other, nframes_t length, const s _flags = Flag (_flags & ~SyncMarked); _sync_position = _start; } - + if (Profile->get_sae()) { /* reset sync point to start if its ended up outside region bounds. @@ -235,10 +242,10 @@ Region::Region (boost::shared_ptr other) : SessionObject(other->session(), other->name()) , _type(other->data_type()) , _flags(Flag(other->_flags & ~(Locked|PositionLocked))) - , _start(other->_start) - , _length(other->_length) - , _position(other->_position) - , _last_position(other->_last_position) + , _start(other->_start) + , _length(other->_length) + , _position(other->_position) + , _last_position(other->_last_position) , _positional_lock_style(other->_positional_lock_style) , _sync_position(other->_sync_position) , _layer(other->_layer) @@ -252,7 +259,10 @@ Region::Region (boost::shared_ptr other) , _read_data_count(0) , _pending_changed(Change(0)) , _last_layer_op(other->_last_layer_op) + , _pending_explicit_relayer (false) { + _flags = Flag (_flags | DoNotSendPropertyChanges); + other->_first_edit = EditChangesName; if (other->_extra_xml) { @@ -268,11 +278,11 @@ Region::Region (boost::shared_ptr other) Region::Region (const SourceList& srcs, const XMLNode& node) : SessionObject(srcs.front()->session(), X_("error: XML did not reset this")) , _type(DataType::NIL) // to be loaded from XML - , _flags(Flag(0)) - , _start(0) - , _length(0) - , _position(0) - , _last_position(0) + , _flags(DoNotSendPropertyChanges) + , _start(0) + , _length(0) + , _position(0) + , _last_position(0) , _positional_lock_style(AudioTime) , _sync_position(_start) , _layer(0) @@ -283,23 +293,11 @@ Region::Region (const SourceList& srcs, const XMLNode& node) , _read_data_count(0) , _pending_changed(Change(0)) , _last_layer_op(0) + , _pending_explicit_relayer (false) { - set > unique_srcs; - - for (SourceList::const_iterator i=srcs.begin(); i != srcs.end(); ++i) { - _sources.push_back (*i); - (*i)->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), (*i))); - unique_srcs.insert (*i); - } - - for (SourceList::const_iterator i = srcs.begin(); i != srcs.end(); ++i) { - _master_sources.push_back (*i); - if (unique_srcs.find (*i) == unique_srcs.end()) { - (*i)->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), (*i))); - } - } + use_sources (srcs); - if (set_state (node)) { + if (set_state (node, Stateful::loading_state_version)) { throw failed_constructor(); } @@ -310,11 +308,11 @@ Region::Region (const SourceList& srcs, const XMLNode& node) Region::Region (boost::shared_ptr src, const XMLNode& node) : SessionObject(src->session(), X_("error: XML did not reset this")) , _type(DataType::NIL) - , _flags(Flag(0)) - , _start(0) - , _length(0) - , _position(0) - , _last_position(0) + , _flags(DoNotSendPropertyChanges) + , _start(0) + , _length(0) + , _position(0) + , _last_position(0) , _positional_lock_style(AudioTime) , _sync_position(_start) , _layer(0) @@ -325,53 +323,42 @@ Region::Region (boost::shared_ptr src, const XMLNode& node) , _read_data_count(0) , _pending_changed(Change(0)) , _last_layer_op(0) + , _pending_explicit_relayer (false) { _sources.push_back (src); - if (set_state (node)) { + if (set_state (node, Stateful::loading_state_version)) { throw failed_constructor(); } - + assert(_type != DataType::NIL); assert(_sources.size() > 0); } Region::~Region () { - boost::shared_ptr pl (playlist()); - - if (pl) { - for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) { - (*i)->remove_playlist (pl); - } - for (SourceList::const_iterator i = _master_sources.begin(); i != _master_sources.end(); ++i) { - (*i)->remove_playlist (pl); - } - } - - notify_callbacks (); - GoingAway (); /* EMIT SIGNAL */ + DEBUG_TRACE (DEBUG::Destruction, string_compose ("Region %1 destructor @ %2\n", _name, this)); } void -Region::copy_stuff (boost::shared_ptr other, nframes_t offset, nframes_t length, const string& name, layer_t layer, Flag flags) +Region::copy_stuff (boost::shared_ptr other, nframes_t /*offset*/, nframes_t length, const string& name, layer_t layer, Flag flags) { _frozen = 0; _pending_changed = Change (0); _read_data_count = 0; _valid_transients = false; - _length = length; - _last_length = length; + _length = length; + _last_length = length; _sync_position = other->_sync_position; _ancestral_start = other->_ancestral_start; - _ancestral_length = other->_ancestral_length; + _ancestral_length = other->_ancestral_length; _stretch = other->_stretch; _shift = other->_shift; _name = name; - _last_position = 0; - _position = 0; - _layer = layer; + _last_position = 0; + _position = 0; + _layer = layer; _flags = Flag (flags & ~(Locked|WholeFile|Hidden)); _first_edit = EditChangesNothing; _last_layer_op = 0; @@ -383,44 +370,7 @@ Region::copy_stuff (boost::shared_ptr other, nframes_t offset, nfr void Region::set_playlist (boost::weak_ptr wpl) { - boost::shared_ptr old_playlist = (_playlist.lock()); - - boost::shared_ptr pl (wpl.lock()); - - if (old_playlist == pl) { - return; - } - - _playlist = pl; - - if (pl) { - if (old_playlist) { - for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) { - (*i)->remove_playlist (_playlist); - (*i)->add_playlist (pl); - } - for (SourceList::const_iterator i = _master_sources.begin(); i != _master_sources.end(); ++i) { - (*i)->remove_playlist (_playlist); - (*i)->add_playlist (pl); - } - } else { - for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) { - (*i)->add_playlist (pl); - } - for (SourceList::const_iterator i = _master_sources.begin(); i != _master_sources.end(); ++i) { - (*i)->add_playlist (pl); - } - } - } else { - if (old_playlist) { - for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) { - (*i)->remove_playlist (old_playlist); - } - for (SourceList::const_iterator i = _master_sources.begin(); i != _master_sources.end(); ++i) { - (*i)->remove_playlist (old_playlist); - } - } - } + _playlist = wpl.lock(); } bool @@ -428,7 +378,7 @@ Region::set_name (const std::string& str) { if (_name != str) { SessionObject::set_name(str); // EMIT SIGNAL NameChanged() - assert(_name == str); + assert(_name == str); send_change (ARDOUR::NameChanged); } @@ -436,7 +386,7 @@ Region::set_name (const std::string& str) } void -Region::set_length (nframes_t len, void *src) +Region::set_length (nframes_t len, void */*src*/) { //cerr << "Region::set_length() len = " << len << endl; if (_flags & Locked) { @@ -445,7 +395,7 @@ Region::set_length (nframes_t len, void *src) if (_length != len && len != 0) { - /* check that the current _position wouldn't make the new + /* check that the current _position wouldn't make the new length impossible. */ @@ -456,7 +406,7 @@ Region::set_length (nframes_t len, void *src) if (!verify_length (len)) { return; } - + _last_length = _length; _length = len; @@ -487,7 +437,7 @@ Region::first_edit () if (_first_edit != EditChangesNothing && pl) { - _name = pl->session().new_region_name (_name); + _name = _session.new_region_name (_name); _first_edit = EditChangesNothing; send_change (ARDOUR::NameChanged); @@ -503,7 +453,7 @@ Region::at_natural_position () const if (!pl) { return false; } - + boost::shared_ptr whole_file_region = get_parent(); if (whole_file_region) { @@ -523,18 +473,18 @@ Region::move_to_natural_position (void *src) if (!pl) { return; } - + boost::shared_ptr whole_file_region = get_parent(); if (whole_file_region) { set_position (whole_file_region->position() + _start, src); } } - + void Region::special_set_position (nframes_t pos) { - /* this is used when creating a whole file region as + /* this is used when creating a whole file region as a way to store its "natural" or "captured" position. */ @@ -554,27 +504,27 @@ Region::set_position_lock_style (PositionLockStyle ps) _positional_lock_style = ps; if (_positional_lock_style == MusicTime) { - pl->session().tempo_map().bbt_time (_position, _bbt_time); + _session.tempo_map().bbt_time (_position, _bbt_time); } - + } void Region::update_position_after_tempo_map_change () { boost::shared_ptr pl (playlist()); - + if (!pl || _positional_lock_style != MusicTime) { return; } - TempoMap& map (pl->session().tempo_map()); + TempoMap& map (_session.tempo_map()); nframes_t pos = map.frame_time (_bbt_time); set_position_internal (pos, false); } void -Region::set_position (nframes_t pos, void *src) +Region::set_position (nframes_t pos, void* /*src*/) { if (!can_move()) { return; @@ -591,7 +541,7 @@ Region::set_position_internal (nframes_t pos, bool allow_bbt_recompute) _position = pos; /* check that the new _position wouldn't make the current - length impossible - if so, change the length. + length impossible - if so, change the length. XXX is this the right thing to do? */ @@ -616,7 +566,7 @@ Region::set_position_internal (nframes_t pos, bool allow_bbt_recompute) } void -Region::set_position_on_top (nframes_t pos, void *src) +Region::set_position_on_top (nframes_t pos, void* /*src*/) { if (_flags & Locked) { return; @@ -636,7 +586,7 @@ Region::set_position_on_top (nframes_t pos, void *src) /* do this even if the position is the same. this helps out a GUI that has moved its representation already. */ - + send_change (PositionChanged); } @@ -644,15 +594,12 @@ void Region::recompute_position_from_lock_style () { if (_positional_lock_style == MusicTime) { - boost::shared_ptr pl (playlist()); - if (pl) { - pl->session().tempo_map().bbt_time (_position, _bbt_time); - } + _session.tempo_map().bbt_time (_position, _bbt_time); } } - + void -Region::nudge_position (nframes64_t n, void *src) +Region::nudge_position (nframes64_t n, void* /*src*/) { if (_flags & Locked) { return; @@ -661,7 +608,7 @@ Region::nudge_position (nframes64_t n, void *src) if (n == 0) { return; } - + _last_position = _position; if (n > 0) { @@ -691,7 +638,7 @@ Region::set_ancestral_data (nframes64_t s, nframes64_t l, float st, float sh) } void -Region::set_start (nframes_t pos, void *src) +Region::set_start (nframes_t pos, void* /*src*/) { if (_flags & (Locked|PositionLocked)) { return; @@ -717,14 +664,14 @@ Region::set_start (nframes_t pos, void *src) } void -Region::trim_start (nframes_t new_position, void *src) +Region::trim_start (nframes_t new_position, void */*src*/) { if (_flags & (Locked|PositionLocked)) { return; } nframes_t new_start; int32_t start_shift; - + if (new_position > _position) { start_shift = new_position - _position; } else { @@ -757,7 +704,7 @@ Region::trim_start (nframes_t new_position, void *src) if (new_start == _start) { return; } - + _start = new_start; _flags = Region::Flag (_flags & ~WholeFile); first_edit (); @@ -782,20 +729,20 @@ Region::trim_front (nframes_t new_position, void *src) } if (new_position < end) { /* can't trim it zero or negative length */ - + nframes_t newlen; /* can't trim it back passed where source position zero is located */ - + new_position = max (new_position, source_zero); - - + + if (new_position > _position) { newlen = _length - (new_position - _position); } else { newlen = _length + (_position - new_position); } - + trim_to_internal (new_position, newlen, src); if (!_frozen) { recompute_at_start (); @@ -803,15 +750,19 @@ Region::trim_front (nframes_t new_position, void *src) } } +/** @param new_endpoint New region end point, such that, for example, + * a region at 0 of length 10 has an endpoint of 9. + */ + void -Region::trim_end (nframes_t new_endpoint, void *src) +Region::trim_end (nframes_t new_endpoint, void */*src*/) { if (_flags & Locked) { return; } if (new_endpoint > _position) { - trim_to_internal (_position, new_endpoint - _position, this); + trim_to_internal (_position, new_endpoint - _position + 1, this); if (!_frozen) { recompute_at_end (); } @@ -834,7 +785,7 @@ Region::trim_to (nframes_t position, nframes_t length, void *src) } void -Region::trim_to_internal (nframes_t position, nframes_t length, void *src) +Region::trim_to_internal (nframes_t position, nframes_t length, void */*src*/) { int32_t start_shift; nframes_t new_start; @@ -893,17 +844,17 @@ Region::trim_to_internal (nframes_t position, nframes_t length, void *src) _position = position; what_changed = Change (what_changed|PositionChanged); } - + _flags = Region::Flag (_flags & ~WholeFile); if (what_changed & (StartChanged|LengthChanged)) { first_edit (); - } + } if (what_changed) { send_change (what_changed); } -} +} void Region::set_hidden (bool yn) @@ -977,12 +928,10 @@ Region::set_position_locked (bool yn) void Region::set_sync_position (nframes_t absolute_pos) { - nframes_t file_pos; - - file_pos = _start + (absolute_pos - _position); + nframes_t const file_pos = _start + (absolute_pos - _position); if (file_pos != _sync_position) { - + _sync_position = file_pos; _flags = Flag (_flags|SyncMarked); @@ -1014,7 +963,7 @@ Region::sync_offset (int& dir) const if (_flags & SyncMarked) { if (_sync_position > _start) { dir = 1; - return _sync_position - _start; + return _sync_position - _start; } else { dir = -1; return _start - _sync_position; @@ -1025,14 +974,14 @@ Region::sync_offset (int& dir) const } } -nframes_t +nframes_t Region::adjust_to_sync (nframes_t pos) const { int sync_dir; nframes_t offset = sync_offset (sync_dir); // cerr << "adjusting pos = " << pos << " to sync at " << _sync_position << " offset = " << offset << " with dir = " << sync_dir << endl; - + if (sync_dir > 0) { if (pos > offset) { pos -= offset; @@ -1052,7 +1001,7 @@ nframes_t Region::sync_position() const { if (_flags & SyncMarked) { - return _sync_position; + return _sync_position; } else { return _start; } @@ -1100,13 +1049,13 @@ Region::set_layer (layer_t l) { if (_layer != l) { _layer = l; - + send_change (LayerChanged); } } XMLNode& -Region::state (bool full_state) +Region::state (bool /*full_state*/) { XMLNode *node = new XMLNode ("Region"); char buf[64]; @@ -1130,7 +1079,7 @@ Region::state (bool full_state) node->add_property ("stretch", buf); snprintf (buf, sizeof (buf), "%.12g", _shift); node->add_property ("shift", buf); - + switch (_first_edit) { case EditChangesNothing: fe = X_("nothing"); @@ -1172,13 +1121,13 @@ Region::get_state () } int -Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) +Region::set_live_state (const XMLNode& node, int /*version*/, Change& what_changed, bool send) { const XMLNodeList& nlist = node.children(); const XMLProperty *prop; nframes_t val; - /* this is responsible for setting those aspects of Region state + /* this is responsible for setting those aspects of Region state that are mutable after construction. */ @@ -1188,7 +1137,7 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) } _name = prop->value(); - + if ((prop = node.property ("type")) == 0) { _type = DataType::AUDIO; } else { @@ -1198,7 +1147,8 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) if ((prop = node.property ("start")) != 0) { sscanf (prop->value().c_str(), "%" PRIu32, &val); if (val != _start) { - what_changed = Change (what_changed|StartChanged); + what_changed = Change (what_changed|StartChanged); + cerr << _name << " start changed\n"; _start = val; } } else { @@ -1209,6 +1159,7 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) sscanf (prop->value().c_str(), "%" PRIu32, &val); if (val != _length) { what_changed = Change (what_changed|LengthChanged); + cerr << _name << " length changed\n"; _last_length = _length; _length = val; } @@ -1221,6 +1172,7 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) sscanf (prop->value().c_str(), "%" PRIu32, &val); if (val != _position) { what_changed = Change (what_changed|PositionChanged); + cerr << _name << " position changed\n"; _last_position = _position; _position = val; } @@ -1234,6 +1186,7 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) x = (layer_t) atoi (prop->value().c_str()); if (x != _layer) { what_changed = Change (what_changed|LayerChanged); + cerr << _name << " layer changed\n"; _layer = x; } } else { @@ -1244,6 +1197,7 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) sscanf (prop->value().c_str(), "%" PRIu32, &val); if (val != _sync_position) { what_changed = Change (what_changed|SyncOffsetChanged); + cerr << _name << " sync changed\n"; _sync_position = val; } } else { @@ -1258,7 +1212,7 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) /* missing BBT info, revert to audio time locking */ _positional_lock_style = AudioTime; } else { - if (sscanf (prop->value().c_str(), "%d|%d|%d", + if (sscanf (prop->value().c_str(), "%d|%d|%d", &_bbt_time.bars, &_bbt_time.beats, &_bbt_time.ticks) != 3) { @@ -1266,13 +1220,13 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) } } } - + } else { _positional_lock_style = AudioTime; } /* XXX FIRST EDIT !!! */ - + /* these 3 properties never change as a result of any editing */ if ((prop = node.property ("ancestral-start")) != 0) { @@ -1282,7 +1236,7 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) } if ((prop = node.property ("ancestral-length")) != 0) { - _ancestral_length = atoi (prop->value()); + _ancestral_length = strtoll (prop->value().c_str(), 0, 10); } else { _ancestral_length = _length; } @@ -1320,11 +1274,11 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) _extra_xml = 0; for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) { - + XMLNode *child; - + child = (*niter); - + if (child->name () == "Extra") { _extra_xml = new XMLNode (*child); break; @@ -1332,6 +1286,7 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) } if (send) { + cerr << _name << ": final change to be sent: " << hex << what_changed << dec << endl; send_change (what_changed); } @@ -1339,7 +1294,7 @@ Region::set_live_state (const XMLNode& node, Change& what_changed, bool send) } int -Region::set_state (const XMLNode& node) +Region::set_state (const XMLNode& node, int version) { const XMLProperty *prop; Change what_changed = Change (0); @@ -1352,10 +1307,10 @@ Region::set_state (const XMLNode& node) } _id = prop->value(); - + _first_edit = EditChangesNothing; - - set_live_state (node, what_changed, true); + + set_live_state (node, version, what_changed, true); return 0; } @@ -1369,7 +1324,7 @@ Region::freeze () } void -Region::thaw (const string& why) +Region::thaw (const string& /*why*/) { Change what_changed = Change (0); @@ -1393,40 +1348,45 @@ Region::thaw (const string& why) if (what_changed & LengthChanged) { if (what_changed & PositionChanged) { recompute_at_start (); - } + } recompute_at_end (); } - - StateChanged (what_changed); + + send_change (what_changed); } void Region::send_change (Change what_changed) { + { Glib::Mutex::Lock lm (_lock); if (_frozen) { _pending_changed = Change (_pending_changed|what_changed); return; - } + } } + cerr << _name << " actually sends " << hex << what_changed << dec << " @" << get_microseconds() << endl; StateChanged (what_changed); - - if (!(_flags & DoNotSaveState)) { - + cerr << _name << " done with " << hex << what_changed << dec << " @" << get_microseconds() << endl; + + if (!(_flags & DoNotSendPropertyChanges)) { + /* Try and send a shared_pointer unless this is part of the constructor. If so, do nothing. */ - + try { boost::shared_ptr rptr = shared_from_this(); + cerr << _name << " actually sends prop change " << hex << what_changed << dec << " @ " << get_microseconds() << endl; RegionPropertyChanged (rptr); + cerr << _name << " done with prop change @ " << get_microseconds() << endl; } catch (...) { /* no shared_ptr available, relax; */ } } - + } void @@ -1463,10 +1423,21 @@ Region::region_list_equivalent (boost::shared_ptr other) const } void -Region::source_deleted (boost::shared_ptr) +Region::source_deleted (boost::weak_ptr) { _sources.clear (); - drop_references (); + + 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 @@ -1486,6 +1457,7 @@ void Region::set_master_sources (const SourceList& srcs) { _master_sources = srcs; + assert (_sources.size() == _master_sources.size()); } bool @@ -1512,6 +1484,17 @@ Region::source_equivalent (boost::shared_ptr other) const return true; } +bool +Region::uses_source (boost::shared_ptr 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 { @@ -1530,9 +1513,9 @@ Region::verify_length (nframes_t len) for (uint32_t n=0; n < _sources.size(); ++n) { maxlen = max (maxlen, (nframes_t)source_length(n) - _start); } - + len = min (len, maxlen); - + return true; } @@ -1592,12 +1575,12 @@ Region::get_parent() const if (pl) { boost::shared_ptr r; boost::shared_ptr grrr2 = boost::dynamic_pointer_cast (shared_from_this()); - - if (grrr2 && (r = pl->session().find_whole_file_parent (grrr2))) { + + if (grrr2 && (r = _session.find_whole_file_parent (grrr2))) { return boost::static_pointer_cast (r); } } - + return boost::shared_ptr(); } @@ -1620,18 +1603,18 @@ void Region::use_sources (SourceList const & s) { set > unique_srcs; - + for (SourceList::const_iterator i = s.begin (); i != s.end(); ++i) { _sources.push_back (*i); - (*i)->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), *i)); + (*i)->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr(*i))); unique_srcs.insert (*i); } - for (SourceList::const_iterator i = s.begin(); i != s.end(); ++i) { + for (SourceList::const_iterator i = s.begin (); i != s.end(); ++i) { _master_sources.push_back (*i); if (unique_srcs.find (*i) == unique_srcs.end()) { - (*i)->GoingAway.connect (bind (mem_fun (*this, &Region::source_deleted), *i)); + (*i)->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr(*i))); } } } - +