From c97bf1a4b75c43dbd9578b2806db875fec762d1e Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 10 Jan 2024 11:46:39 -0700 Subject: [PATCH] Revert "separate out all bounds/position info from Region into "Slice"" This reverts commit f3da2cfd8b9dc077ee35fc3bbaf133adec23d463. --- libs/ardour/ardour/region.h | 88 +++++++++++++++- libs/ardour/ardour/slice.h | 122 ----------------------- libs/ardour/region.cc | 139 +++++++++++++++++++++++--- libs/ardour/slice.cc | 193 ------------------------------------ libs/ardour/wscript | 1 - 5 files changed, 213 insertions(+), 330 deletions(-) delete mode 100644 libs/ardour/ardour/slice.h delete mode 100644 libs/ardour/slice.cc diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index 27f954a161..e288300481 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -41,7 +41,6 @@ #include "ardour/movable.h" #include "ardour/readable.h" #include "ardour/session_object.h" -#include "ardour/slice.h" #include "ardour/trimmable.h" #include "ardour/types_convert.h" @@ -68,6 +67,8 @@ namespace Properties { LIBARDOUR_API extern PBD::PropertyDescriptor hidden; LIBARDOUR_API extern PBD::PropertyDescriptor position_locked; LIBARDOUR_API extern PBD::PropertyDescriptor valid_transients; // used for signal only + LIBARDOUR_API extern PBD::PropertyDescriptor start; + LIBARDOUR_API extern PBD::PropertyDescriptor length; LIBARDOUR_API extern PBD::PropertyDescriptor sync_position; LIBARDOUR_API extern PBD::PropertyDescriptor layer; LIBARDOUR_API extern PBD::PropertyDescriptor ancestral_start; @@ -100,7 +101,6 @@ enum LIBARDOUR_API RegionOperationFlag { class LIBARDOUR_API Region : public SessionObject , public std::enable_shared_from_this - , public Slice , public Trimmable , public Movable , public Temporal::TimeDomainSwapper @@ -126,6 +126,27 @@ public: void start_domain_bounce (Temporal::DomainBounceInfo&); void finish_domain_bounce (Temporal::DomainBounceInfo&); + /** How the region parameters play together: + * + * POSITION: first sample of the region along the timeline + * START: first sample of the region within its source(s) + * LENGTH: number of samples the region represents + */ + + timepos_t position () const { return _length.val().position(); } + timepos_t start () const { return _start.val(); } + timecnt_t length () const { return _length.val(); } + timepos_t end() const; + timepos_t nt_last() const { return end().decrement(); } + + timepos_t source_position () const; + timecnt_t source_relative_position (Temporal::timepos_t const &) const; + timecnt_t region_relative_position (Temporal::timepos_t const &) const; + + samplepos_t position_sample () const { return position().samples(); } + samplecnt_t start_sample () const { return _start.val().samples(); } + samplecnt_t length_samples () const { return _length.val().samples(); } + layer_t layer () const { return _layer; } void set_selected_for_solo(bool yn); @@ -133,6 +154,11 @@ public: timepos_t source_length (uint32_t n) const; uint32_t max_source_level () const; + /* these two are valid ONLY during a StateChanged signal handler */ + + timepos_t last_position () const { return _last_length.position(); } + timecnt_t last_length () const { return _last_length; } + samplecnt_t ancestral_start_sample () const { return _ancestral_start.val().samples(); } samplecnt_t ancestral_length_samples () const { return _ancestral_length.val().samples(); } timepos_t ancestral_start () const { return _ancestral_start.val(); } @@ -206,8 +232,33 @@ public: timepos_t sync_position () const; timepos_t adjust_to_sync (timepos_t const &) const; + + /* first_sample() is an alias; last_sample() just hides some math */ + + samplepos_t first_sample () const { return position().samples(); } + samplepos_t last_sample () const { return first_sample() + length_samples() - 1; } + + /** Return the earliest possible value of _position given the + * value of _start within the region's sources + */ + timepos_t earliest_possible_position () const; + /** Return the last possible value of _last_sample given the + * value of _startin the regions's sources + */ samplepos_t latest_possible_sample () const; + Temporal::TimeRange last_range () const { + return Temporal::TimeRange (last_position(), last_position() + _last_length); + } + + Temporal::TimeRange range_samples () const { + return Temporal::TimeRange (timepos_t (first_sample()), timepos_t (first_sample() + length_samples())); + } + + Temporal::TimeRange range () const { + return Temporal::TimeRange (position(), position() + length()); + } + bool hidden () const { return _hidden; } bool muted () const { return _muted; } bool opaque () const { return _opaque; } @@ -224,6 +275,7 @@ public: Trimmable::CanTrim can_trim () const; + Temporal::TimeDomain position_time_domain () const; void set_position_time_domain (Temporal::TimeDomain ps); void recompute_position_from_time_domain (); @@ -259,6 +311,7 @@ public: std::string source_string () const; + /* EDITING OPERATIONS */ void set_length (timecnt_t const &); @@ -306,6 +359,34 @@ public: void modify_front_unchecked (timepos_t const & new_position, bool reset_fade); void modify_end_unchecked (timepos_t const & new_position, bool reset_fade); + Temporal::timepos_t region_beats_to_absolute_time(Temporal::Beats beats) const; + /** Convert a timestamp in beats into timepos_t (both relative to region position) */ + Temporal::timepos_t region_beats_to_region_time (Temporal::Beats beats) const { + return timepos_t (position().distance (region_beats_to_absolute_time (beats))); + } + /** Convert a timestamp in beats relative to region position into beats relative to source start */ + Temporal::Beats region_beats_to_source_beats (Temporal::Beats beats) const { + return position().distance (region_beats_to_absolute_time (beats)).beats (); + } + /** Convert a distance within a region to beats relative to region position */ + Temporal::Beats region_distance_to_region_beats (Temporal::timecnt_t const &) const; + + /** Convert a timestamp in beats measured from source start into absolute beats */ + Temporal::Beats source_beats_to_absolute_beats(Temporal::Beats beats) const; + + /** Convert a timestamp in beats measured from source start into absolute samples */ + Temporal::timepos_t source_beats_to_absolute_time(Temporal::Beats beats) const; + + /** Convert a timestamp in beats measured from source start into region-relative samples */ + Temporal::timepos_t source_beats_to_region_time(Temporal::Beats beats) const { + return timepos_t (position().distance (source_beats_to_absolute_time (beats))); + } + /** Convert a timestamp in absolute time to beats measured from source start*/ + Temporal::Beats absolute_time_to_source_beats(Temporal::timepos_t const &) const; + + Temporal::Beats absolute_time_to_region_beats (Temporal::timepos_t const &) const; + + Temporal::timepos_t absolute_time_to_region_time (Temporal::timepos_t const &) const; int apply (Filter &, PBD::Progress* progress = 0); @@ -469,6 +550,8 @@ protected: PBD::Property _left_of_split; PBD::Property _right_of_split; PBD::Property _valid_transients; + PBD::Property _start; + PBD::Property _length; /** Sync position relative to the start of our file */ PBD::Property _sync_position; @@ -526,6 +609,7 @@ private: PBD::Property _reg_group; PBD::Property _contents; // type is irrelevant + timecnt_t _last_length; mutable RegionEditState _first_edit; layer_t _layer; diff --git a/libs/ardour/ardour/slice.h b/libs/ardour/ardour/slice.h deleted file mode 100644 index d5b05e41f4..0000000000 --- a/libs/ardour/ardour/slice.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef __libardour_slice_h__ -#define __libardour_slice_h__ - -#include "pbd/properties.h" -#include "pbd/stateful.h" - -#include "temporal/timeline.h" -#include "temporal/range.h" - -#include "ardour/libardour_visibility.h" -#include "ardour/types.h" -#include "ardour/types_convert.h" - -namespace ARDOUR { - -namespace Properties { - LIBARDOUR_API extern PBD::PropertyDescriptor start; - LIBARDOUR_API extern PBD::PropertyDescriptor length; -} - -class LIBARDOUR_API Slice : virtual public PBD::Stateful -{ - public: - Slice (Temporal::timepos_t const &, Temporal::timecnt_t const &); - Slice (Slice const &); - virtual ~Slice() {} - - Slice& operator= (Slice const &); - - timepos_t position () const { return _length.val().position(); } - timepos_t start () const { return _start.val(); } - timecnt_t length () const { return _length.val(); } - timepos_t end() const; - timepos_t nt_last() const { return end().decrement(); } - - /* these two are valid ONLY during a StateChanged signal handler */ - - timepos_t last_position () const { return _last_length.position(); } - timecnt_t last_length () const { return _last_length; } - - timepos_t source_position () const; - timecnt_t source_relative_position (Temporal::timepos_t const &) const; - timecnt_t region_relative_position (Temporal::timepos_t const &) const; - - samplepos_t position_sample () const { return position().samples(); } - samplecnt_t start_sample () const { return _start.val().samples(); } - samplecnt_t length_samples () const { return _length.val().samples(); } - - - /* first_sample() is an alias; last_sample() just hides some math */ - - samplepos_t first_sample () const { return position().samples(); } - samplepos_t last_sample () const { return first_sample() + length_samples() - 1; } - - /** Return the earliest possible value of _position given the - * value of _start within the region's sources - */ - timepos_t earliest_possible_position () const; - /** Return the last possible value of _last_sample given the - * value of _startin the regions's sources - */ - samplepos_t latest_possible_sample () const; - - Temporal::TimeRange last_range () const { - return Temporal::TimeRange (last_position(), last_position() + _last_length); - } - - Temporal::TimeRange range_samples () const { - return Temporal::TimeRange (timepos_t (first_sample()), timepos_t (first_sample() + length_samples())); - } - - Temporal::TimeRange range () const { - return Temporal::TimeRange (position(), position() + length()); - } - - Temporal::timepos_t region_beats_to_absolute_time(Temporal::Beats beats) const; - /** Convert a timestamp in beats into timepos_t (both relative to region position) */ - Temporal::timepos_t region_beats_to_region_time (Temporal::Beats beats) const { - return timepos_t (position().distance (region_beats_to_absolute_time (beats))); - } - /** Convert a timestamp in beats relative to region position into beats relative to source start */ - Temporal::Beats region_beats_to_source_beats (Temporal::Beats beats) const { - return position().distance (region_beats_to_absolute_time (beats)).beats (); - } - /** Convert a distance within a region to beats relative to region position */ - Temporal::Beats region_distance_to_region_beats (Temporal::timecnt_t const &) const; - - /** Convert a timestamp in beats measured from source start into absolute beats */ - Temporal::Beats source_beats_to_absolute_beats(Temporal::Beats beats) const; - - /** Convert a timestamp in beats measured from source start into absolute samples */ - Temporal::timepos_t source_beats_to_absolute_time(Temporal::Beats beats) const; - - /** Convert a timestamp in beats measured from source start into region-relative samples */ - Temporal::timepos_t source_beats_to_region_time(Temporal::Beats beats) const { - return timepos_t (position().distance (source_beats_to_absolute_time (beats))); - } - /** Convert a timestamp in absolute time to beats measured from source start*/ - Temporal::Beats absolute_time_to_source_beats(Temporal::timepos_t const &) const; - - Temporal::Beats absolute_time_to_region_beats (Temporal::timepos_t const &) const; - - Temporal::timepos_t absolute_time_to_region_time (Temporal::timepos_t const &) const; - - Temporal::TimeDomain position_time_domain () const; - - protected: - PBD::Property _start; - PBD::Property _length; - timecnt_t _last_length; - - virtual void set_length_internal (timecnt_t const &); - virtual void set_start_internal (timepos_t const &); - virtual void set_position_internal (timepos_t const &); - - private: - void register_properties (); -}; - -} /* namespace */ - -#endif /* __libardour_slice_h__ */ diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 0dd0e28846..ad24525baa 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -227,6 +227,8 @@ Region::register_properties () , _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)) \ , _sync_position (Properties::sync_position, (s)) \ , _transient_user_start (0) \ , _transient_analysis_start (0) \ @@ -256,6 +258,8 @@ Region::register_properties () , _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) \ , _sync_position(Properties::sync_position, other->_sync_position) \ , _user_transients (other->_user_transients) \ , _transient_user_start (other->_transient_user_start) \ @@ -285,9 +289,9 @@ Region::register_properties () /* derived-from-derived constructor (no sources in constructor) */ Region::Region (Session& s, timepos_t const & start, timecnt_t const & length, const string& name, DataType type) : SessionObject(s, name) - , Slice (start, length) , _type (type) , REGION_DEFAULT_STATE (start,length) + , _last_length (length) , _first_edit (EditChangesNothing) , _layer (0) , _changemap (0) @@ -300,11 +304,10 @@ Region::Region (Session& s, timepos_t const & start, timecnt_t const & length, c /** Basic Region constructor (many sources) */ Region::Region (const SourceList& srcs) : SessionObject(srcs.front()->session(), "toBeRenamed") - , Slice (_type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t::from_superclock (0), - _type == DataType::MIDI ? timecnt_t (Temporal::Beats()) : timecnt_t::from_superclock (0)) , _type (srcs.front()->type()) , REGION_DEFAULT_STATE(_type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t::from_superclock (0), _type == DataType::MIDI ? timecnt_t (Temporal::Beats()) : timecnt_t::from_superclock (0)) + , _last_length (_type == DataType::MIDI ? timecnt_t (Temporal::Beats()) : timecnt_t::from_superclock (0)) , _first_edit (EditChangesNothing) , _layer (0) , _changemap (0) @@ -322,9 +325,9 @@ Region::Region (const SourceList& srcs) /** Create a new Region from an existing one */ Region::Region (std::shared_ptr other) : SessionObject(other->session(), other->name()) - , Slice (*other.get()) , _type (other->data_type()) , REGION_COPY_STATE (other) + , _last_length (other->_last_length) , _first_edit (EditChangesNothing) , _layer (other->_layer) , _changemap (other->_changemap) @@ -380,9 +383,9 @@ Region::Region (std::shared_ptr other) */ Region::Region (std::shared_ptr other, timecnt_t const & offset) : SessionObject(other->session(), other->name()) - , Slice (*other.get()) , _type (other->data_type()) , REGION_COPY_STATE (other) + , _last_length (other->_last_length) , _first_edit (EditChangesNothing) , _layer (other->_layer) , _changemap (other->_changemap) @@ -425,9 +428,9 @@ Region::Region (std::shared_ptr other, timecnt_t const & offset) /** Create a copy of @p other but with different sources. Used by filters */ Region::Region (std::shared_ptr other, const SourceList& srcs) : SessionObject (other->session(), other->name()) - , Slice (*other.get()) , _type (srcs.front()->type()) , REGION_COPY_STATE (other) + , _last_length (other->_last_length) , _first_edit (EditChangesID) , _layer (other->_layer) , _changemap (other->_changemap) @@ -578,12 +581,6 @@ Region::maybe_uncopy () /* this does nothing but marked a semantic moment once upon a time */ } -void -Region::set_start_internal (timepos_t const & s) -{ - _start = s; -} - void Region::first_edit () { @@ -2154,6 +2151,22 @@ Region::is_compound () const return max_source_level() > 0; } +void +Region::set_start_internal (timepos_t const & s) +{ + _start = s; +} + +timepos_t +Region::earliest_possible_position () const +{ + if (start() > timecnt_t (position(), timepos_t())) { + return timepos_t::from_superclock (0); + } else { + return source_position(); + } +} + samplecnt_t Region::latest_possible_sample () const { @@ -2173,6 +2186,108 @@ Region::latest_possible_sample () const return (position() + minlen).samples() - 1; } +Temporal::TimeDomain +Region::position_time_domain() const +{ + return position().time_domain(); +} + +timepos_t +Region::end() const +{ + /* one day we might want to enforce _position, _start and _length (or + some combination thereof) all being in the same time domain. + */ + return _length.val().end(); +} + +timepos_t +Region::source_position () const +{ + /* this is the position of the start of the source, in absolute time */ + return position().earlier (_start.val()); +} + +Temporal::Beats +Region::region_distance_to_region_beats (timecnt_t const & region_relative_offset) const +{ + return timecnt_t (region_relative_offset, position()).beats (); +} + +Temporal::Beats +Region::source_beats_to_absolute_beats (Temporal::Beats beats) const +{ + /* since the return type must be beats, force source_position() to + beats before adding, rather than after. + */ + return source_position().beats() + beats; +} + +Temporal::Beats +Region::absolute_time_to_region_beats(timepos_t const & b) const +{ + return (position().distance (b)).beats () + start().beats(); +} + +Temporal::timepos_t +Region::absolute_time_to_region_time (timepos_t const & t) const +{ + return start() + position().distance (t); +} + +Temporal::timepos_t +Region::region_beats_to_absolute_time (Temporal::Beats beats) const +{ + return position() + timepos_t (beats); +} + +Temporal::timepos_t +Region::source_beats_to_absolute_time (Temporal::Beats beats) const +{ + /* return the time corresponding to `beats' relative to the start of + the source. The start of the source is an implied position given by + region->position - region->start aka ::source_position() + */ + return source_position() + timepos_t (beats); +} + +/** Calculate (time - source_position) in Beats + * + * Measure the distance between the absolute time and the position of + * the source start, in beats. The result is positive if time is later + * than source position. + * + * @param p is an absolute time + * @returns time offset from p to the region's source position as the origin in Beat units + */ +Temporal::Beats +Region::absolute_time_to_source_beats(timepos_t const& p) const +{ + return source_position().distance (p).beats(); +} + +/** Calculate (pos - source-position) + * + * @param p is an absolute time + * @returns time offset from p to the region's source position as the origin. + */ +timecnt_t +Region::source_relative_position (timepos_t const & p) const +{ + return source_position().distance (p); +} + +/** Calculate (p - region-position) + * + * @param p is an absolute time + * @returns the time offset using the region (timeline) position as origin + */ +timecnt_t +Region::region_relative_position (timepos_t const & p) const +{ + return position().distance (p); +} + Temporal::TimeDomain Region::time_domain() const { diff --git a/libs/ardour/slice.cc b/libs/ardour/slice.cc deleted file mode 100644 index 55d5a6d20f..0000000000 --- a/libs/ardour/slice.cc +++ /dev/null @@ -1,193 +0,0 @@ -#include "ardour/slice.h" - -using namespace ARDOUR; -using namespace Temporal; - -Slice::Slice (timepos_t const & s, timecnt_t const & l) - : _start (Properties::start, s) - , _length (Properties::length, l) - , _last_length (l) -{ - register_properties (); -} - -Slice::Slice (Slice const & other) - : _start (Properties::start, other._start) - , _length (Properties::length, other._length) - , _last_length (other._last_length) -{ -} - -void -Slice::register_properties () -{ - add_property (_start); - add_property (_length); -} - -timepos_t -Slice::source_position () const -{ - /* this is the position of the start of the source, in absolute time */ - return position().earlier (_start.val()); -} - -Temporal::Beats -Slice::region_distance_to_region_beats (timecnt_t const & region_relative_offset) const -{ - return timecnt_t (region_relative_offset, position()).beats (); -} - -Temporal::Beats -Slice::source_beats_to_absolute_beats (Temporal::Beats beats) const -{ - /* since the return type must be beats, force source_position() to - beats before adding, rather than after. - */ - return source_position().beats() + beats; -} - -Temporal::Beats -Slice::absolute_time_to_region_beats(timepos_t const & b) const -{ - return (position().distance (b)).beats () + start().beats(); -} - -Temporal::timepos_t -Slice::absolute_time_to_region_time (timepos_t const & t) const -{ - return start() + position().distance (t); -} - -Temporal::timepos_t -Slice::region_beats_to_absolute_time (Temporal::Beats beats) const -{ - return position() + timepos_t (beats); -} - -Temporal::timepos_t -Slice::source_beats_to_absolute_time (Temporal::Beats beats) const -{ - /* return the time corresponding to `beats' relative to the start of - the source. The start of the source is an implied position given by - region->position - region->start aka ::source_position() - */ - return source_position() + timepos_t (beats); -} - -/** Calculate (time - source_position) in Beats - * - * Measure the distance between the absolute time and the position of - * the source start, in beats. The result is positive if time is later - * than source position. - * - * @param p is an absolute time - * @returns time offset from p to the region's source position as the origin in Beat units - */ -Temporal::Beats -Slice::absolute_time_to_source_beats(timepos_t const& p) const -{ - return source_position().distance (p).beats(); -} - -/** Calculate (pos - source-position) - * - * @param p is an absolute time - * @returns time offset from p to the region's source position as the origin. - */ -timecnt_t -Slice::source_relative_position (timepos_t const & p) const -{ - return source_position().distance (p); -} - -/** Calculate (p - region-position) - * - * @param p is an absolute time - * @returns the time offset using the region (timeline) position as origin - */ -timecnt_t -Slice::region_relative_position (timepos_t const & p) const -{ - return position().distance (p); -} - - -Temporal::TimeDomain -Slice::position_time_domain() const -{ - return position().time_domain(); -} - -timepos_t -Slice::end() const -{ - /* one day we might want to enforce _position, _start and _length (or - some combination thereof) all being in the same time domain. - */ - return _length.val().end(); -} - - -void -Slice::set_start_internal (timepos_t const & s) -{ - _start = s; -} - -void -Slice::set_length_internal (timecnt_t const & len) -{ - /* maintain position value of both _last_length and _length. - * - * This is very important: set_length() can only be used to the length - * component of _length, and set_position() can only be used to set the - * position component. - */ - - _last_length = timecnt_t (_length.val().distance(), _last_length.position()); - _length = timecnt_t (len.distance(), _length.val().position()); -} - -void -Slice::set_position_internal (timepos_t const & pos) -{ - if (position() == pos) { - return; - } - - /* We emit a change of Properties::length even if the position hasn't changed - * (see Slice::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. - * - * maintain length value of both _last_length and _length. - * - * This is very important: set_length() can only be used to the length - * component of _length, and set_position() can only be used to set the - * position component. - */ - - _last_length.set_position (position()); - _length = timecnt_t (_length.val().distance(), pos); - - /* check that the new _position wouldn't make the current - * length impossible - if so, change the length. - * - * XXX is this the right thing to do? - */ - if (timepos_t::max (_length.val().time_domain()).earlier (_length) < position()) { - _last_length = _length; - _length = position().distance (timepos_t::max (position().time_domain())); - } -} - -timepos_t -Slice::earliest_possible_position () const -{ - if (start() > timecnt_t (position(), timepos_t())) { - return timepos_t::from_superclock (0); - } else { - return source_position(); - } -} - diff --git a/libs/ardour/wscript b/libs/ardour/wscript index c79319b2e3..57494c0c9e 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -233,7 +233,6 @@ libardour_sources = [ 'simple_export.cc', 'slavable.cc', 'slavable_automation_control.cc', - 'slice.cc', 'smf_source.cc', 'sndfile_helpers.cc', 'sndfileimportable.cc',