X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fregion.cc;h=66c0b84ae9c201f66264614ab1760a6f32627e2d;hb=ecae912da9f6805d4939e657e3a591f79b0ae542;hp=7fb94bb1778adebf20e9cbfd93bf614175ed090b;hpb=70126fb9d6bbac5c001eeffa870f0ecc83741fc8;p=ardour.git diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 7fb94bb177..66c0b84ae9 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -29,14 +29,17 @@ #include "pbd/enumwriter.h" #include "ardour/debug.h" -#include "ardour/region.h" +#include "ardour/file_source.h" +#include "ardour/filter.h" #include "ardour/playlist.h" +#include "ardour/playlist_source.h" +#include "ardour/profile.h" +#include "ardour/region.h" +#include "ardour/region_factory.h" #include "ardour/session.h" #include "ardour/source.h" +#include "ardour/source_factory.h" #include "ardour/tempo.h" -#include "ardour/region_factory.h" -#include "ardour/filter.h" -#include "ardour/profile.h" #include "ardour/utils.h" #include "i18n.h" @@ -45,7 +48,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -namespace ARDOUR { +namespace ARDOUR { namespace Properties { PBD::PropertyDescriptor muted; PBD::PropertyDescriptor opaque; @@ -70,9 +73,10 @@ namespace ARDOUR { PBD::PropertyDescriptor stretch; PBD::PropertyDescriptor shift; PBD::PropertyDescriptor position_lock_style; + PBD::PropertyDescriptor layering_index; } } - + PBD::Signal2,const PropertyChange&> Region::RegionPropertyChanged; void @@ -124,6 +128,8 @@ Region::make_property_quarks () 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)); + 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)); } void @@ -148,63 +154,63 @@ Region::register_properties () add_property (_length); add_property (_position); add_property (_sync_position); - add_property (_layer); add_property (_ancestral_start); add_property (_ancestral_length); add_property (_stretch); add_property (_shift); add_property (_position_lock_style); + add_property (_layering_index); } #define REGION_DEFAULT_STATE(s,l) \ - _muted (Properties::muted, false) \ + _sync_marked (Properties::sync_marked, false) \ + , _left_of_split (Properties::left_of_split, false) \ + , _right_of_split (Properties::right_of_split, false) \ + , _valid_transients (Properties::valid_transients, false) \ + , _start (Properties::start, (s)) \ + , _length (Properties::length, (l)) \ + , _position (Properties::position, 0) \ + , _sync_position (Properties::sync_position, (s)) \ + , _muted (Properties::muted, false) \ , _opaque (Properties::opaque, true) \ , _locked (Properties::locked, false) \ , _automatic (Properties::automatic, false) \ , _whole_file (Properties::whole_file, false) \ , _import (Properties::import, false) \ , _external (Properties::external, false) \ - , _sync_marked (Properties::sync_marked, false) \ - , _left_of_split (Properties::left_of_split, false) \ - , _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) \ - , _sync_position (Properties::sync_position, (s)) \ - , _layer (Properties::layer, 0) \ , _ancestral_start (Properties::ancestral_start, (s)) \ , _ancestral_length (Properties::ancestral_length, (l)) \ , _stretch (Properties::stretch, 1.0) \ , _shift (Properties::shift, 1.0) \ - , _position_lock_style (Properties::position_lock_style, _type == DataType::AUDIO ? AudioTime : MusicTime) + , _position_lock_style (Properties::position_lock_style, _type == DataType::AUDIO ? AudioTime : MusicTime) \ + , _layering_index (Properties::layering_index, 0) #define REGION_COPY_STATE(other) \ - _muted (Properties::muted, other->_muted) \ + _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) \ + , _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) \ + , _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) + , _position_lock_style (Properties::position_lock_style, other->_position_lock_style) \ + , _layering_index (Properties::layering_index, other->_layering_index) /* derived-from-derived constructor (no sources in constructor) */ Region::Region (Session& s, framepos_t start, framecnt_t length, const string& name, DataType type) @@ -214,9 +220,7 @@ Region::Region (Session& s, framepos_t start, framecnt_t length, const string& n , _last_length (length) , _last_position (0) , _first_edit (EditChangesNothing) - , _read_data_count(0) - , _last_layer_op(0) - , _pending_explicit_relayer (false) + , _layer (0) { register_properties (); @@ -231,9 +235,7 @@ Region::Region (const SourceList& srcs) , _last_length (0) , _last_position (0) , _first_edit (EditChangesNothing) - , _read_data_count(0) - , _last_layer_op (0) - , _pending_explicit_relayer (false) + , _layer (0) { register_properties (); @@ -253,10 +255,7 @@ Region::Region (boost::shared_ptr other) , _last_length (other->_last_length) , _last_position(other->_last_position) \ , _first_edit (EditChangesNothing) - , _read_data_count(0) - , _last_layer_op (0) - , _pending_explicit_relayer (false) - + , _layer (other->_layer) { register_properties (); @@ -278,14 +277,14 @@ Region::Region (boost::shared_ptr other) /* 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. - + 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->sync_marked()) { if (other->_start < other->_sync_position) { /* sync pos was after the start point of the other region */ @@ -326,10 +325,7 @@ Region::Region (boost::shared_ptr other, frameoffset_t offset) , _last_length (other->_last_length) , _last_position(other->_last_position) \ , _first_edit (EditChangesNothing) - , _read_data_count(0) - , _last_layer_op (0) - , _pending_explicit_relayer (false) - + , _layer (other->_layer) { register_properties (); @@ -344,12 +340,12 @@ Region::Region (boost::shared_ptr other, frameoffset_t offset) use_sources (other->_sources); _start = other->_start + offset; - + /* 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. */ - + if (other->sync_marked()) { if (other->_sync_position < _start) { _sync_marked = false; @@ -384,9 +380,7 @@ Region::Region (boost::shared_ptr other, const SourceList& srcs) , _last_length (other->_last_length) , _last_position (other->_last_position) , _first_edit (EditChangesID) - , _read_data_count (0) - , _last_layer_op (other->_last_layer_op) - , _pending_explicit_relayer (false) + , _layer (other->_layer) { register_properties (); @@ -431,7 +425,7 @@ Region::set_name (const std::string& str) } void -Region::set_length (framecnt_t len, void */*src*/) +Region::set_length (framecnt_t len) { //cerr << "Region::set_length() len = " << len << endl; if (locked()) { @@ -517,7 +511,7 @@ Region::at_natural_position () const } void -Region::move_to_natural_position (void *src) +Region::move_to_natural_position () { boost::shared_ptr pl (playlist()); @@ -528,7 +522,7 @@ Region::move_to_natural_position (void *src) boost::shared_ptr whole_file_region = get_parent(); if (whole_file_region) { - set_position (whole_file_region->position() + _start, src); + set_position (whole_file_region->position() + _start); } } @@ -549,24 +543,19 @@ Region::set_position_lock_style (PositionLockStyle ps) if (_position_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); + _session.bbt_time (_position, _bbt_time); } send_change (Properties::position_lock_style); - } } void -Region::update_position_after_tempo_map_change () +Region::update_after_tempo_map_change () { boost::shared_ptr pl (playlist()); @@ -585,7 +574,7 @@ Region::update_position_after_tempo_map_change () } void -Region::set_position (framepos_t pos, void* /*src*/) +Region::set_position (framepos_t pos) { if (!can_move()) { return; @@ -597,14 +586,19 @@ Region::set_position (framepos_t pos, void* /*src*/) a GUI that has moved its representation already. */ send_change (Properties::position); - + } void Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute) { + /* We emit a change of Properties::position even if the position hasn't changed + (see Region::set_position), so we must always set this up so that + e.g. Playlist::notify_region_moved doesn't use an out-of-date last_position. + */ + _last_position = _position; + if (_position != pos) { - _last_position = _position; _position = pos; /* check that the new _position wouldn't make the current @@ -626,39 +620,16 @@ Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute) } } -void -Region::set_position_on_top (framepos_t pos, void* /*src*/) -{ - if (locked()) { - return; - } - - if (_position != pos) { - set_position_internal (pos, true); - } - - boost::shared_ptr pl (playlist()); - - if (pl) { - pl->raise_region_to_top (shared_from_this ()); - } - - /* do this even if the position is the same. this helps out - a GUI that has moved its representation already. - */ - send_change (Properties::position); -} - void Region::recompute_position_from_lock_style () { if (_position_lock_style == MusicTime) { - _session.tempo_map().bbt_time (_position, _bbt_time); + _session.bbt_time (_position, _bbt_time); } } void -Region::nudge_position (frameoffset_t n, void* /*src*/) +Region::nudge_position (frameoffset_t n) { if (locked()) { return; @@ -699,7 +670,7 @@ Region::set_ancestral_data (framepos_t s, framecnt_t l, float st, float sh) } void -Region::set_start (framepos_t pos, void* /*src*/) +Region::set_start (framepos_t pos) { if (locked() || position_locked()) { return; @@ -725,7 +696,7 @@ Region::set_start (framepos_t pos, void* /*src*/) } void -Region::trim_start (framepos_t new_position, void */*src*/) +Region::trim_start (framepos_t new_position) { if (locked() || position_locked()) { return; @@ -752,7 +723,7 @@ Region::trim_start (framepos_t new_position, void */*src*/) } else { new_start = _start + start_shift; } - + } else { return; } @@ -769,25 +740,25 @@ Region::trim_start (framepos_t new_position, void */*src*/) } void -Region::trim_front (framepos_t new_position, void *src) +Region::trim_front (framepos_t new_position) { - modify_front (new_position, false, src); + modify_front (new_position, false); } void -Region::cut_front (framepos_t new_position, void *src) +Region::cut_front (framepos_t new_position) { - modify_front (new_position, true, src); + modify_front (new_position, true); } void -Region::cut_end (framepos_t new_endpoint, void *src) +Region::cut_end (framepos_t new_endpoint) { - modify_end (new_endpoint, true, src); + modify_end (new_endpoint, true); } void -Region::modify_front (framepos_t new_position, bool reset_fade, void *src) +Region::modify_front (framepos_t new_position, bool reset_fade) { if (locked()) { return; @@ -803,7 +774,7 @@ Region::modify_front (framepos_t new_position, bool reset_fade, void *src) } if (new_position < end) { /* can't trim it zero or negative length */ - + framecnt_t newlen = 0; framepos_t delta = 0; @@ -811,7 +782,7 @@ Region::modify_front (framepos_t new_position, bool reset_fade, void *src) /* can't trim it back past 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); @@ -819,17 +790,17 @@ Region::modify_front (framepos_t new_position, bool reset_fade, void *src) newlen = _length + (_position - new_position); delta = _position - new_position; } - - trim_to_internal (new_position, newlen, src); - + + trim_to_internal (new_position, newlen); + if (reset_fade) { _right_of_split = true; } - + if (!property_changes_suspended()) { recompute_at_start (); } - + if (_transients.size() > 0){ adjust_transients(delta); } @@ -837,14 +808,14 @@ Region::modify_front (framepos_t new_position, bool reset_fade, void *src) } void -Region::modify_end (framepos_t new_endpoint, bool reset_fade, void* /*src*/) +Region::modify_end (framepos_t new_endpoint, bool reset_fade) { if (locked()) { return; } if (new_endpoint > _position) { - trim_to_internal (_position, new_endpoint - _position +1, this); + trim_to_internal (_position, new_endpoint - _position); if (reset_fade) { _left_of_split = true; } @@ -859,19 +830,19 @@ Region::modify_end (framepos_t new_endpoint, bool reset_fade, void* /*src*/) */ void -Region::trim_end (framepos_t new_endpoint, void* src) +Region::trim_end (framepos_t new_endpoint) { - modify_end (new_endpoint, false, src); + modify_end (new_endpoint, false); } void -Region::trim_to (framepos_t position, framecnt_t length, void *src) +Region::trim_to (framepos_t position, framecnt_t length) { if (locked()) { return; } - trim_to_internal (position, length, src); + trim_to_internal (position, length); if (!property_changes_suspended()) { recompute_at_start (); @@ -880,7 +851,7 @@ Region::trim_to (framepos_t position, framecnt_t length, void *src) } void -Region::trim_to_internal (framepos_t position, framecnt_t length, void */*src*/) +Region::trim_to_internal (framepos_t position, framecnt_t length) { framepos_t new_start; @@ -920,13 +891,15 @@ Region::trim_to_internal (framepos_t position, framecnt_t length, void */*src*/) _start = new_start; what_changed.add (Properties::start); } - if (_length != length) { - if (!property_changes_suspended()) { - _last_length = _length; - } - set_length_internal (length); - what_changed.add (Properties::length); - } + + /* Set position before length, otherwise for MIDI regions this bad thing happens: + * 1. we call set_length_internal; length in beats is computed using the region's current + * (soon-to-be old) position + * 2. we call set_position_internal; position is set and length in frames re-computed using + * length in beats from (1) but at the new position, which is wrong if the region + * straddles a tempo/meter change. + */ + if (_position != position) { if (!property_changes_suspended()) { _last_position = _position; @@ -935,6 +908,14 @@ Region::trim_to_internal (framepos_t position, framecnt_t length, void */*src*/) what_changed.add (Properties::position); } + if (_length != length) { + if (!property_changes_suspended()) { + _last_length = _length; + } + set_length_internal (length); + what_changed.add (Properties::length); + } + _whole_file = false; PropertyChange start_and_length; @@ -1136,11 +1117,7 @@ Region::lower_to_bottom () void Region::set_layer (layer_t l) { - if (_layer != l) { - _layer = l; - - send_change (Properties::layer); - } + _layer = l; } XMLNode& @@ -1154,7 +1131,7 @@ Region::state () add_properties (*node); - _id.print (buf, sizeof (buf)); + id().print (buf, sizeof (buf)); node->add_property ("id", buf); node->add_property ("type", _type.to_string()); @@ -1195,6 +1172,28 @@ Region::state () node->add_property (buf2, buf); } + /* Only store nested sources for the whole-file region that acts + as the parent/root of all regions using it. + */ + + if (_whole_file && max_source_level() > 0) { + + XMLNode* nested_node = new XMLNode (X_("NestedSource")); + + /* region is compound - get its playlist and + store that before we list the region that + needs it ... + */ + + for (SourceList::const_iterator s = _sources.begin(); s != _sources.end(); ++s) { + nested_node->add_child_nocopy ((*s)->get_state ()); + } + + if (nested_node) { + node->add_child_nocopy (*nested_node); + } + } + if (_extra_xml) { node->add_child_copy (*_extra_xml); } @@ -1220,11 +1219,11 @@ Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_c { const XMLProperty* prop; + Stateful::save_extra_xml (node); + what_changed = set_values (node); - if ((prop = node.property (X_("id")))) { - _id = prop->value(); - } + set_id (node); if (_position_lock_style == MusicTime) { if ((prop = node.property ("bbt-position")) == 0) { @@ -1246,37 +1245,22 @@ Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_c if (_stretch == 0.0f) { _stretch = 1.0f; } - + if (_shift == 0.0f) { _shift = 1.0f; } - const XMLNodeList& nlist = node.children(); - - for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) { - - XMLNode *child; - - child = (*niter); - - if (child->name () == "Extra") { - delete _extra_xml; - _extra_xml = new XMLNode (*child); - break; - } - } - if (send) { send_change (what_changed); } - + /* Quick fix for 2.x sessions when region is muted */ if ((prop = node.property (X_("flags")))) { if (string::npos != prop->value().find("Muted")){ set_muted (true); } } - + return 0; } @@ -1309,8 +1293,8 @@ Region::send_change (const PropertyChange& what_changed) Stateful::send_change (what_changed); - if (!Stateful::frozen()) { - + if (!Stateful::property_changes_suspended()) { + /* Try and send a shared_pointer unless this is part of the constructor. If so, do nothing. */ @@ -1324,12 +1308,6 @@ Region::send_change (const PropertyChange& what_changed) } } -void -Region::set_last_layer_op (uint64_t when) -{ - _last_layer_op = when; -} - bool Region::overlap_equivalent (boost::shared_ptr other) const { @@ -1408,7 +1386,7 @@ 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; @@ -1439,7 +1417,7 @@ Region::source_string () const stringstream res; res << _sources.size() << ":"; - + SourceList::const_iterator i; for (i = _sources.begin(); i != _sources.end(); ++i) { @@ -1460,7 +1438,16 @@ Region::uses_source (boost::shared_ptr source) const if (*i == source) { return true; } + + boost::shared_ptr ps = boost::dynamic_pointer_cast (*i); + + if (ps) { + if (ps->playlist()->uses_source (source)) { + return true; + } + } } + return false; } @@ -1566,7 +1553,7 @@ Region::invalidate_transients () { _valid_transients = false; _transients.clear (); - + send_change (PropertyChange (Properties::valid_transients)); } @@ -1617,7 +1604,7 @@ Region::can_trim () const return ct; } - /* if not locked, we can always move the front later, and the end earlier + /* if not locked, we can always move the front later, and the end earlier */ ct = CanTrim (ct | FrontTrimLater | EndTrimEarlier); @@ -1634,4 +1621,30 @@ Region::can_trim () const return ct; } - + +uint32_t +Region::max_source_level () const +{ + uint32_t lvl = 0; + + for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) { + lvl = max (lvl, (*i)->level()); + } + + return lvl; +} + +bool +Region::is_compound () const +{ + return max_source_level() > 0; +} + +void +Region::post_set (const PropertyChange& pc) +{ + if (pc.contains (Properties::position)) { + recompute_position_from_lock_style (); + } +} +