#include <algorithm>
#include <sstream>
-
#include <glibmm/thread.h>
#include "pbd/xml++.h"
#include "pbd/stacktrace.h"
PBD::PropertyDescriptor<bool> right_of_split;
PBD::PropertyDescriptor<bool> hidden;
PBD::PropertyDescriptor<bool> position_locked;
+ PBD::PropertyDescriptor<bool> valid_transients;
PBD::PropertyDescriptor<framepos_t> start;
PBD::PropertyDescriptor<framecnt_t> length;
PBD::PropertyDescriptor<framepos_t> position;
PBD::PropertyDescriptor<framecnt_t> ancestral_length;
PBD::PropertyDescriptor<float> stretch;
PBD::PropertyDescriptor<float> shift;
+ PBD::PropertyDescriptor<PositionLockStyle> position_lock_style;
}
}
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"));
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
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);
add_property (_ancestral_length);
add_property (_stretch);
add_property (_shift);
+ add_property (_position_lock_style);
}
#define REGION_DEFAULT_STATE(s,l) \
, _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) \
, _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)
, 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)
, 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)
/** 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<const Region> other, frameoffset_t offset, bool offset_relative)
: SessionObject(other->session(), other->name())
, 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)
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) {
, 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)
, 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)
Region::~Region ()
{
DEBUG_TRACE (DEBUG::Destruction, string_compose ("Region %1 destructor @ %2\n", _name, this));
+ drop_sources ();
}
void
void
Region::set_position_lock_style (PositionLockStyle ps)
{
- boost::shared_ptr<Playlist> pl (playlist());
+ if (_position_lock_style != ps) {
- if (!pl) {
- return;
- }
-
- _positional_lock_style = ps;
+ boost::shared_ptr<Playlist> 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
{
boost::shared_ptr<Playlist> pl (playlist());
- if (!pl || _positional_lock_style != MusicTime) {
+ if (!pl || _position_lock_style != MusicTime) {
return;
}
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);
}
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);
}
}
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;
}
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)
{
new_start = _start + start_shift;
}
-
} else if (start_shift < 0) {
if (_start < -start_shift) {
} else {
new_start = _start + start_shift;
}
+
} else {
new_start = _start;
}
}
}
+/** 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) {
}
}
+/* @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;
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;
}
}
}
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);
/* 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
{
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
}
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);
}
void
Region::source_deleted (boost::weak_ptr<Source>)
{
- _sources.clear ();
+ drop_sources ();
if (!_session.deletion_in_progress()) {
/* this is a very special case: at least one of the region's
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
{
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;
sframes_t
Region::source_length(uint32_t n) const
{
+ assert (n < _sources.size());
return _sources[n]->length(_position - _start);
}
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);
}
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);
}
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;
}
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;
}
{
_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)->DropReferences.connect_same_thread (*this, boost::bind (&Region::source_deleted, this, boost::weak_ptr<Source>(*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<Source>(*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<Source>(*i)));
}
- }
-
- return prop_list;
+ }
}