X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fregion.cc;h=43506c78becd10ae1469afa2df52dd6f1c671522;hb=3150041423a199189c9b6ab292a078c51d9670c2;hp=8625b17a8a8276b11c14bea9a852f5ecc68ffe1b;hpb=afc5e3bd0251dbcdbde27036569eb1acab026991;p=ardour.git diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 8625b17a8a..43506c78be 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -23,7 +23,6 @@ #include #include - #include #include "pbd/xml++.h" #include "pbd/stacktrace.h" @@ -60,6 +59,7 @@ namespace ARDOUR { PBD::PropertyDescriptor right_of_split; PBD::PropertyDescriptor hidden; PBD::PropertyDescriptor position_locked; + PBD::PropertyDescriptor valid_transients; PBD::PropertyDescriptor start; PBD::PropertyDescriptor length; PBD::PropertyDescriptor position; @@ -69,6 +69,7 @@ namespace ARDOUR { PBD::PropertyDescriptor ancestral_length; PBD::PropertyDescriptor stretch; PBD::PropertyDescriptor shift; + PBD::PropertyDescriptor position_lock_style; } } @@ -101,6 +102,8 @@ Region::make_property_quarks () 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")); 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")); + 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")); 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")); @@ -119,6 +122,8 @@ Region::make_property_quarks () 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")); 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")); + DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position_lock_style = %1\n", Properties::position_lock_style.property_id)); } void @@ -138,6 +143,7 @@ Region::register_properties () add_property (_right_of_split); add_property (_hidden); add_property (_position_locked); + add_property (_valid_transients); add_property (_start); add_property (_length); add_property (_position); @@ -147,6 +153,7 @@ Region::register_properties () add_property (_ancestral_length); add_property (_stretch); add_property (_shift); + add_property (_position_lock_style); } #define REGION_DEFAULT_STATE(s,l) \ @@ -162,6 +169,7 @@ Region::register_properties () , _right_of_split (Properties::right_of_split, false) \ , _hidden (Properties::hidden, false) \ , _position_locked (Properties::position_locked, false) \ + , _valid_transients (Properties::valid_transients, false) \ , _start (Properties::start, (s)) \ , _length (Properties::length, (l)) \ , _position (Properties::position, 0) \ @@ -170,30 +178,33 @@ Region::register_properties () , _ancestral_start (Properties::ancestral_start, (s)) \ , _ancestral_length (Properties::ancestral_length, (l)) \ , _stretch (Properties::stretch, 1.0) \ - , _shift (Properties::shift, 1.0) + , _shift (Properties::shift, 1.0) \ + , _position_lock_style (Properties::position_lock_style, _type == DataType::AUDIO ? AudioTime : MusicTime) #define REGION_COPY_STATE(other) \ - _muted (other->_muted) \ - , _opaque (other->_opaque) \ - , _locked (other->_locked) \ - , _automatic (other->_automatic) \ - , _whole_file (other->_whole_file) \ - , _import (other->_import) \ - , _external (other->_external) \ - , _sync_marked (other->_sync_marked) \ - , _left_of_split (other->_left_of_split) \ - , _right_of_split (other->_right_of_split) \ - , _hidden (other->_hidden) \ - , _position_locked (other->_position_locked) \ - , _start(other->_start) \ - , _length(other->_length) \ - , _position(other->_position) \ - , _sync_position(other->_sync_position) \ - , _layer (other->_layer) \ - , _ancestral_start (other->_ancestral_start) \ - , _ancestral_length (other->_ancestral_length) \ - , _stretch (other->_stretch) \ - , _shift (other->_shift) + _muted (Properties::muted, other->_muted) \ + , _opaque (Properties::opaque, other->_opaque) \ + , _locked (Properties::locked, other->_locked) \ + , _automatic (Properties::automatic, other->_automatic) \ + , _whole_file (Properties::whole_file, other->_whole_file) \ + , _import (Properties::import, other->_import) \ + , _external (Properties::external, other->_external) \ + , _sync_marked (Properties::sync_marked, other->_sync_marked) \ + , _left_of_split (Properties::left_of_split, other->_left_of_split) \ + , _right_of_split (Properties::right_of_split, other->_right_of_split) \ + , _hidden (Properties::hidden, other->_hidden) \ + , _position_locked (Properties::position_locked, other->_position_locked) \ + , _valid_transients (Properties::valid_transients, other->_valid_transients) \ + , _start(Properties::start, other->_start) \ + , _length(Properties::length, other->_length) \ + , _position(Properties::position, other->_position) \ + , _sync_position(Properties::sync_position, other->_sync_position) \ + , _layer (Properties::layer, other->_layer) \ + , _ancestral_start (Properties::ancestral_start, other->_ancestral_start) \ + , _ancestral_length (Properties::ancestral_length, other->_ancestral_length) \ + , _stretch (Properties::stretch, other->_stretch) \ + , _shift (Properties::shift, other->_shift) \ + , _position_lock_style (Properties::position_lock_style, other->_position_lock_style) /* derived-from-derived constructor (no sources in constructor) */ Region::Region (Session& s, framepos_t start, framecnt_t length, const string& name, DataType type) @@ -202,7 +213,6 @@ Region::Region (Session& s, framepos_t start, framecnt_t length, const string& n , REGION_DEFAULT_STATE(start,length) , _last_length (length) , _last_position (0) - , _positional_lock_style(AudioTime) , _first_edit (EditChangesNothing) , _read_data_count(0) , _last_layer_op(0) @@ -220,9 +230,7 @@ Region::Region (const SourceList& srcs) , REGION_DEFAULT_STATE(0,0) , _last_length (0) , _last_position (0) - , _positional_lock_style (_type == DataType::AUDIO ? AudioTime : MusicTime) , _first_edit (EditChangesNothing) - , _valid_transients(false) , _read_data_count(0) , _last_layer_op (0) , _pending_explicit_relayer (false) @@ -239,10 +247,10 @@ Region::Region (const SourceList& srcs) /** Create a new Region from part of an existing one, starting at one of two places: - if @param offset_relative is true, then the start within @param other is given by @param offset - (i.e. relative to the start of @param other's sources, the start is @param offset + @param other.start() + if \a offset_relative is true, then the start within \a other is given by \a offset + (i.e. relative to the start of \a other's sources, the start is \a offset + \a other.start() - if @param offset_relative is false, then the start within the source is given @param offset. + if @param offset_relative is false, then the start within the source is given \a offset. */ Region::Region (boost::shared_ptr other, frameoffset_t offset, bool offset_relative) : SessionObject(other->session(), other->name()) @@ -250,9 +258,7 @@ Region::Region (boost::shared_ptr other, frameoffset_t offset, boo , REGION_COPY_STATE (other) , _last_length (other->_last_length) , _last_position(other->_last_position) \ - , _positional_lock_style(other->_positional_lock_style) \ , _first_edit (EditChangesNothing) - , _valid_transients(false) , _read_data_count(0) , _last_layer_op (0) , _pending_explicit_relayer (false) @@ -276,7 +282,7 @@ Region::Region (boost::shared_ptr other, frameoffset_t offset, boo property lists. this would be nice to remove. */ - _positional_lock_style = other->_positional_lock_style; + _position_lock_style = other->_position_lock_style; _first_edit = other->_first_edit; if (offset == 0) { @@ -357,9 +363,7 @@ Region::Region (boost::shared_ptr other, const SourceList& srcs) , REGION_COPY_STATE (other) , _last_length (other->_last_length) , _last_position (other->_last_position) - , _positional_lock_style (other->_positional_lock_style) , _first_edit (EditChangesID) - , _valid_transients (false) , _read_data_count (0) , _last_layer_op (other->_last_layer_op) , _pending_explicit_relayer (false) @@ -388,9 +392,7 @@ Region::Region (boost::shared_ptr other) , REGION_COPY_STATE (other) , _last_length (other->_last_length) , _last_position (other->_last_position) - , _positional_lock_style (other->_positional_lock_style) , _first_edit (EditChangesID) - , _valid_transients(false) , _read_data_count(0) , _last_layer_op(other->_last_layer_op) , _pending_explicit_relayer (false) @@ -415,6 +417,7 @@ Region::Region (boost::shared_ptr other) Region::~Region () { DEBUG_TRACE (DEBUG::Destruction, string_compose ("Region %1 destructor @ %2\n", _name, this)); + drop_sources (); } void @@ -544,18 +547,22 @@ Region::special_set_position (framepos_t pos) void Region::set_position_lock_style (PositionLockStyle ps) { - boost::shared_ptr pl (playlist()); + if (_position_lock_style != ps) { - if (!pl) { - return; - } - - _positional_lock_style = ps; + boost::shared_ptr pl (playlist()); + + if (!pl) { + return; + } + + _position_lock_style = ps; + + if (_position_lock_style == MusicTime) { + _session.tempo_map().bbt_time (_position, _bbt_time); + } - if (_positional_lock_style == MusicTime) { - _session.tempo_map().bbt_time (_position, _bbt_time); + send_change (Properties::position_lock_style); } - } void @@ -563,7 +570,7 @@ Region::update_position_after_tempo_map_change () { boost::shared_ptr pl (playlist()); - if (!pl || _positional_lock_style != MusicTime) { + if (!pl || _position_lock_style != MusicTime) { return; } @@ -604,13 +611,12 @@ Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute) recompute_position_from_lock_style (); } - invalidate_transients (); + //invalidate_transients (); } /* do this even if the position is the same. this helps out a GUI that has moved its representation already. */ - send_change (Properties::position); } @@ -642,7 +648,7 @@ Region::set_position_on_top (framepos_t pos, void* /*src*/) void Region::recompute_position_from_lock_style () { - if (_positional_lock_style == MusicTime) { + if (_position_lock_style == MusicTime) { _session.tempo_map().bbt_time (_position, _bbt_time); } } @@ -763,13 +769,31 @@ Region::trim_start (framepos_t new_position, void */*src*/) void Region::trim_front (framepos_t new_position, void *src) +{ + modify_front (new_position, false, src); +} + +void +Region::cut_front (nframes_t new_position, void *src) +{ + modify_front (new_position, true, src); +} + +void +Region::cut_end (nframes_t new_endpoint, void *src) +{ + modify_end (new_endpoint, true, src); +} + +void +Region::modify_front (nframes_t new_position, bool reset_fade, void *src) { if (locked()) { return; } - framepos_t end = last_frame(); - framepos_t source_zero; + nframes_t end = last_frame(); + nframes_t source_zero; if (_position > _start) { source_zero = _position - _start; @@ -778,46 +802,66 @@ Region::trim_front (framepos_t new_position, void *src) } if (new_position < end) { /* can't trim it zero or negative length */ - - framecnt_t newlen; + + nframes_t newlen = 0; + nframes64_t delta = 0; /* 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); + delta = -1 * (new_position - _position); } else { newlen = _length + (_position - new_position); + delta = _position - new_position; } - + trim_to_internal (new_position, newlen, src); - if (!property_changes_suspended()) { + + if (reset_fade) { + _right_of_split = true; + } + + if (!property_changes_suspended()) { recompute_at_start (); } + + if (_transients.size() > 0){ + adjust_transients(delta); + } } } -/** @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 (framepos_t new_endpoint, void */*src*/) +Region::modify_end (nframes_t new_endpoint, bool reset_fade, void *src) { if (locked()) { return; } if (new_endpoint > _position) { - trim_to_internal (_position, new_endpoint - _position + 1, this); + trim_to_internal (_position, new_endpoint - _position +1, this); + if (reset_fade) { + _left_of_split = true; + } if (!property_changes_suspended()) { recompute_at_end (); } } } +/** @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 (framepos_t new_endpoint, void* src) +{ + modify_end (new_endpoint, false, src); +} + void Region::trim_to (framepos_t position, framecnt_t length, void *src) { @@ -857,7 +901,6 @@ Region::trim_to_internal (framepos_t position, framecnt_t length, void */*src*/) new_start = _start + start_shift; } - } else if (start_shift < 0) { if (_start < -start_shift) { @@ -865,6 +908,7 @@ Region::trim_to_internal (framepos_t position, framecnt_t length, void */*src*/) } else { new_start = _start + start_shift; } + } else { new_start = _start; } @@ -969,9 +1013,13 @@ Region::set_position_locked (bool yn) } } +/** Set the region's sync point. + * @param absolute_pos Session time. + */ void Region::set_sync_position (framepos_t absolute_pos) { + /* position within our file */ framepos_t const file_pos = _start + (absolute_pos - _position); if (file_pos != _sync_position) { @@ -996,11 +1044,10 @@ Region::clear_sync_position () } } +/* @return the sync point relative the first frame of the region */ framepos_t Region::sync_offset (int& dir) const { - /* returns the sync point relative the first frame of the region */ - if (sync_marked()) { if (_sync_position > _start) { dir = 1; @@ -1038,13 +1085,15 @@ Region::adjust_to_sync (framepos_t pos) const return pos; } +/** @return Sync position in session time */ framepos_t Region::sync_position() const { if (sync_marked()) { - return _sync_position; + return _position - _start + _sync_position; } else { - return _start; + /* if sync has not been marked, use the start of the region */ + return _position; } } @@ -1096,10 +1145,12 @@ Region::set_layer (layer_t l) } XMLNode& -Region::state (bool /*full_state*/) +Region::state () { XMLNode *node = new XMLNode ("Region"); char buf[64]; + char buf2[64]; + LocaleGuard lg (X_("POSIX")); const char* fe = NULL; add_properties (*node); @@ -1127,20 +1178,35 @@ Region::state (bool /*full_state*/) /* note: flags are stored by derived classes */ - if (_positional_lock_style != AudioTime) { - node->add_property ("positional-lock-style", enum_2_string (_positional_lock_style)); + if (_position_lock_style != AudioTime) { stringstream str; str << _bbt_time; node->add_property ("bbt-position", str.str()); } + for (uint32_t n=0; n < _sources.size(); ++n) { + snprintf (buf2, sizeof(buf2), "source-%d", n); + _sources[n]->id().print (buf, sizeof(buf)); + node->add_property (buf2, buf); + } + + for (uint32_t n=0; n < _master_sources.size(); ++n) { + snprintf (buf2, sizeof(buf2), "master-source-%d", n); + _master_sources[n]->id().print (buf, sizeof (buf)); + node->add_property (buf2, buf); + } + + if (_extra_xml) { + node->add_child_copy (*_extra_xml); + } + return *node; } XMLNode& Region::get_state () { - return state (true); + return state (); } int @@ -1155,29 +1221,24 @@ Region::_set_state (const XMLNode& node, int version, PropertyChange& what_chang { const XMLProperty* prop; - what_changed = set_properties (node); + what_changed = set_values (node); if ((prop = node.property (X_("id")))) { _id = prop->value(); } - if ((prop = node.property ("positional-lock-style")) != 0) { - _positional_lock_style = PositionLockStyle (string_2_enum (prop->value(), _positional_lock_style)); - - if (_positional_lock_style == MusicTime) { - if ((prop = node.property ("bbt-position")) == 0) { - /* missing BBT info, revert to audio time locking */ - _positional_lock_style = AudioTime; - } else { - if (sscanf (prop->value().c_str(), "%d|%d|%d", - &_bbt_time.bars, - &_bbt_time.beats, - &_bbt_time.ticks) != 3) { - _positional_lock_style = AudioTime; - } + if (_position_lock_style == MusicTime) { + if ((prop = node.property ("bbt-position")) == 0) { + /* missing BBT info, revert to audio time locking */ + _position_lock_style = AudioTime; + } else { + if (sscanf (prop->value().c_str(), "%d|%d|%d", + &_bbt_time.bars, + &_bbt_time.beats, + &_bbt_time.ticks) != 3) { + _position_lock_style = AudioTime; } } - } /* fix problems with old sessions corrupted by impossible @@ -1207,11 +1268,6 @@ Region::_set_state (const XMLNode& node, int version, PropertyChange& what_chang } if (send) { - cerr << _name << ": final change to be sent: "; - for (PropertyChange::iterator i = what_changed.begin(); i != what_changed.end(); ++i) { - cerr << g_quark_to_string ((GQuark) *i) << ' '; - } - cerr << endl; send_change (what_changed); } @@ -1305,7 +1361,7 @@ Region::region_list_equivalent (boost::shared_ptr other) const void Region::source_deleted (boost::weak_ptr) { - _sources.clear (); + drop_sources (); if (!_session.deletion_in_progress()) { /* this is a very special case: at least one of the region's @@ -1336,8 +1392,16 @@ Region::master_source_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 @@ -1345,6 +1409,11 @@ Region::source_equivalent (boost::shared_ptr 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; @@ -1378,6 +1447,7 @@ Region::uses_source (boost::shared_ptr source) const sframes_t Region::source_length(uint32_t n) const { + assert (n < _sources.size()); return _sources[n]->length(_position - _start); } @@ -1390,7 +1460,7 @@ Region::verify_length (framecnt_t len) framecnt_t maxlen = 0; - for (uint32_t n=0; n < _sources.size(); ++n) { + for (uint32_t n = 0; n < _sources.size(); ++n) { maxlen = max (maxlen, source_length(n) - _start); } @@ -1408,7 +1478,7 @@ Region::verify_start_and_length (framepos_t new_start, framecnt_t& new_length) framecnt_t maxlen = 0; - for (uint32_t n=0; n < _sources.size(); ++n) { + for (uint32_t n = 0; n < _sources.size(); ++n) { maxlen = max (maxlen, source_length(n) - new_start); } @@ -1424,7 +1494,7 @@ Region::verify_start (framepos_t pos) return true; } - for (uint32_t n=0; n < _sources.size(); ++n) { + for (uint32_t n = 0; n < _sources.size(); ++n) { if (pos > source_length(n) - _length) { return false; } @@ -1439,7 +1509,7 @@ Region::verify_start_mutable (framepos_t& new_start) return true; } - for (uint32_t n=0; n < _sources.size(); ++n) { + for (uint32_t n = 0; n < _sources.size(); ++n) { if (new_start > source_length(n) - _length) { new_start = source_length(n) - _length; } @@ -1476,8 +1546,25 @@ 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) @@ -1485,31 +1572,18 @@ 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)->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) { + _sources.push_back (*i); + (*i)->inc_use_count (); _master_sources.push_back (*i); - if (unique_srcs.find (*i) == unique_srcs.end()) { - (*i)->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr(*i))); - } - } -} - -PropertyList* -Region::property_factory (const XMLNode& history_node) const -{ - PropertyList* prop_list = new PropertyList; + (*i)->inc_use_count (); - for (OwnedPropertyList::const_iterator i = _properties->begin(); i != _properties->end(); ++i) { - PropertyBase* prop = i->second->maybe_clone_self_if_found_in_history_node (history_node); + /* connect only once to DropReferences, even if sources are replicated + */ - if (prop) { - prop_list->add (prop); + 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(*i))); } - } - - return prop_list; + } }