first round of changes to use timeline types, here basically for Region position/length/start
UNFINISHED WORK. Does not compile. But region.cc will compile, hence this snapshot
This commit is contained in:
parent
b5bf518a0a
commit
d40bdf5e95
|
@ -113,7 +113,6 @@ class LIBARDOUR_API AudioRegion : public Region
|
|||
/* Readable interface */
|
||||
|
||||
virtual samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const;
|
||||
virtual samplecnt_t readable_length() const { return length(); }
|
||||
|
||||
virtual samplecnt_t read_at (Sample *buf, Sample *mixdown_buf, float *gain_buf,
|
||||
samplepos_t position,
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
~AudioRom();
|
||||
|
||||
samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const;
|
||||
samplecnt_t readable_length() const { return _size; }
|
||||
samplecnt_t readable_length_samples() const { return _size; }
|
||||
uint32_t n_channels () const { return 1; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -77,7 +77,6 @@ class LIBARDOUR_API MidiRegion : public Region
|
|||
|
||||
/* Stub Readable interface */
|
||||
virtual samplecnt_t read (Sample*, samplepos_t /*pos*/, samplecnt_t /*cnt*/, int /*channel*/) const { return 0; }
|
||||
virtual samplecnt_t readable_length() const { return length(); }
|
||||
|
||||
samplecnt_t read_at (Evoral::EventSink<samplepos_t>& dst,
|
||||
samplepos_t position,
|
||||
|
@ -157,12 +156,11 @@ class LIBARDOUR_API MidiRegion : public Region
|
|||
|
||||
bool set_name (const std::string & str);
|
||||
|
||||
void set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
|
||||
void set_position_music_internal (double qn);
|
||||
void set_length_internal (samplecnt_t len, const int32_t sub_num);
|
||||
void set_start_internal (samplecnt_t, const int32_t sub_num);
|
||||
void trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num);
|
||||
void update_length_beats (const int32_t sub_num);
|
||||
void set_position_internal (timepos_t pos);
|
||||
void set_length_internal (timecnt_t const & len);
|
||||
void set_start_internal (timecnt_t const &);
|
||||
void trim_to_internal (timepos_t position, timecnt_t const & length);
|
||||
void update_length_beats ();
|
||||
|
||||
void model_changed ();
|
||||
void model_contents_changed ();
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
load (Session&, std::string const&);
|
||||
|
||||
virtual samplecnt_t read (Sample*, samplepos_t pos, samplecnt_t cnt, int channel) const = 0;
|
||||
virtual samplecnt_t readable_length() const = 0;
|
||||
virtual samplecnt_t readable_length_samples() const = 0;
|
||||
virtual uint32_t n_channels () const = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include "temporal/timeline.h"
|
||||
|
||||
#include "pbd/undo.h"
|
||||
#include "pbd/signals.h"
|
||||
#include "ardour/ardour.h"
|
||||
|
@ -59,14 +61,14 @@ namespace Properties {
|
|||
LIBARDOUR_API extern PBD::PropertyDescriptor<bool> hidden;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<bool> position_locked;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<bool> valid_transients;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<samplepos_t> start;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<samplecnt_t> length;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<samplepos_t> position;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> start;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> length;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<timepos_t> position;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<double> beat;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<samplecnt_t> sync_position;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> sync_position;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<layer_t> layer;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<samplepos_t> ancestral_start;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<samplecnt_t> ancestral_length;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> ancestral_start;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<timecnt_t> ancestral_length;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<float> stretch;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<float> shift;
|
||||
LIBARDOUR_API extern PBD::PropertyDescriptor<PositionLockStyle> position_lock_style;
|
||||
|
@ -116,9 +118,22 @@ public:
|
|||
* START: first sample of the region within its source(s)
|
||||
* LENGTH: number of samples the region represents
|
||||
*/
|
||||
samplepos_t position () const { return _position; }
|
||||
samplepos_t start () const { return _start; }
|
||||
samplecnt_t length () const { return _length; }
|
||||
|
||||
timepos_t nt_position () const { return _position.val(); }
|
||||
timecnt_t nt_start () const { return _start.val(); }
|
||||
timecnt_t nt_length () const { return _length.val(); }
|
||||
timepos_t nt_end() const;
|
||||
|
||||
timepos_t source_position () const;
|
||||
timepos_t source_relative_position (Temporal::timepos_t const &) const;
|
||||
timepos_t region_relative_position (Temporal::timepos_t const &) const;
|
||||
|
||||
samplepos_t position_sample () const { return _position.val().samples(); }
|
||||
samplecnt_t start_sample () const { return _start.val().samples(); }
|
||||
samplecnt_t length_samples () const { return _length.val().samples(); }
|
||||
|
||||
samplecnt_t readable_length_samples() const { return length_samples(); }
|
||||
|
||||
layer_t layer () const { return _layer; }
|
||||
|
||||
void set_selected_for_solo(bool yn);
|
||||
|
@ -128,38 +143,41 @@ public:
|
|||
|
||||
/* these two are valid ONLY during a StateChanged signal handler */
|
||||
|
||||
samplepos_t last_position () const { return _last_position; }
|
||||
samplecnt_t last_length () const { return _last_length; }
|
||||
timepos_t last_position () const { return _last_position; }
|
||||
timecnt_t last_length () const { return _last_length; }
|
||||
|
||||
samplepos_t ancestral_start () const { return _ancestral_start; }
|
||||
samplecnt_t ancestral_length () const { return _ancestral_length; }
|
||||
samplecnt_t ancestral_start_sample () const { return _ancestral_start.val().samples(); }
|
||||
samplecnt_t ancestral_length_samples () const { return _ancestral_length.val().samples(); }
|
||||
timecnt_t ancestral_start () const { return _ancestral_start.val(); }
|
||||
timecnt_t ancestral_length () const { return _ancestral_length.val(); }
|
||||
|
||||
float stretch () const { return _stretch; }
|
||||
float shift () const { return _shift; }
|
||||
|
||||
void set_ancestral_data (samplepos_t start, samplecnt_t length, float stretch, float shift);
|
||||
void set_ancestral_data (timecnt_t const & start, timecnt_t const & length, float stretch, float shift);
|
||||
|
||||
sampleoffset_t sync_offset (int& dir) const;
|
||||
samplepos_t sync_position () const;
|
||||
timecnt_t sync_offset (int& dir) const;
|
||||
timepos_t sync_position () const;
|
||||
|
||||
samplepos_t adjust_to_sync (samplepos_t) const;
|
||||
timepos_t adjust_to_sync (timepos_t) const;
|
||||
|
||||
/* first_sample() is an alias; last_sample() just hides some math */
|
||||
|
||||
samplepos_t first_sample () const { return _position; }
|
||||
samplepos_t last_sample () const { return _position + _length - 1; }
|
||||
samplepos_t first_sample () const { return _position.val().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
|
||||
*/
|
||||
samplepos_t earliest_possible_position () const;
|
||||
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;
|
||||
|
||||
Evoral::Range<samplepos_t> last_range () const {
|
||||
return Evoral::Range<samplepos_t> (_last_position, _last_position + _last_length - 1);
|
||||
//return Evoral::Range<samplepos_t> (_last_position, _last_position + _last_length - 1);
|
||||
return Evoral::Range<samplepos_t> (0, 0);
|
||||
}
|
||||
|
||||
Evoral::Range<samplepos_t> range () const {
|
||||
|
@ -184,7 +202,7 @@ public:
|
|||
|
||||
PositionLockStyle position_lock_style () const { return _position_lock_style; }
|
||||
void set_position_lock_style (PositionLockStyle ps);
|
||||
void recompute_position_from_lock_style (const int32_t sub_num);
|
||||
void recompute_position_from_lock_style ();
|
||||
|
||||
/* meter-based beat at the region position */
|
||||
double beat () const { return _beat; }
|
||||
|
@ -224,27 +242,27 @@ public:
|
|||
|
||||
/* EDITING OPERATIONS */
|
||||
|
||||
void set_length (samplecnt_t, const int32_t sub_num);
|
||||
void set_start (samplepos_t);
|
||||
void set_position (samplepos_t, int32_t sub_num = 0);
|
||||
void set_position_music (double qn);
|
||||
void set_initial_position (samplepos_t);
|
||||
void special_set_position (samplepos_t);
|
||||
void set_length (timecnt_t const &);
|
||||
void set_start (timecnt_t const &);
|
||||
void set_position (timepos_t);
|
||||
void set_initial_position (timepos_t);
|
||||
void special_set_position (timepos_t);
|
||||
virtual void update_after_tempo_map_change (bool send_change = true);
|
||||
void nudge_position (sampleoffset_t);
|
||||
void nudge_position (timecnt_t const &);
|
||||
|
||||
bool at_natural_position () const;
|
||||
void move_to_natural_position ();
|
||||
|
||||
void move_start (sampleoffset_t distance, const int32_t sub_num = 0);
|
||||
void trim_front (samplepos_t new_position, const int32_t sub_num = 0);
|
||||
void trim_end (samplepos_t new_position, const int32_t sub_num = 0);
|
||||
void trim_to (samplepos_t position, samplecnt_t length, const int32_t sub_num = 0);
|
||||
void move_start (timecnt_t const & distance);
|
||||
void trim_front (timepos_t new_position);
|
||||
void trim_end (timepos_t new_position);
|
||||
void trim_to (timepos_t pos, timecnt_t const & length);
|
||||
|
||||
/* fades are inherently audio in nature and we specify them in samples */
|
||||
virtual void fade_range (samplepos_t, samplepos_t) {}
|
||||
|
||||
void cut_front (samplepos_t new_position, const int32_t sub_num = 0);
|
||||
void cut_end (samplepos_t new_position, const int32_t sub_num = 0);
|
||||
void cut_front (timepos_t new_position);
|
||||
void cut_end (timepos_t new_position);
|
||||
|
||||
void set_layer (layer_t l); /* ONLY Playlist can call this */
|
||||
void raise ();
|
||||
|
@ -252,7 +270,7 @@ public:
|
|||
void raise_to_top ();
|
||||
void lower_to_bottom ();
|
||||
|
||||
void set_sync_position (samplepos_t n);
|
||||
void set_sync_position (timepos_t n);
|
||||
void clear_sync_position ();
|
||||
void set_hidden (bool yn);
|
||||
void set_muted (bool yn);
|
||||
|
@ -389,13 +407,13 @@ protected:
|
|||
Region (boost::shared_ptr<const Region>);
|
||||
|
||||
/** Construct a region from another region, at an offset within that region */
|
||||
Region (boost::shared_ptr<const Region>, ARDOUR::MusicSample start_offset);
|
||||
Region (boost::shared_ptr<const Region>, timecnt_t start_offset);
|
||||
|
||||
/** Construct a region as a copy of another region, but with different sources */
|
||||
Region (boost::shared_ptr<const Region>, const SourceList&);
|
||||
|
||||
/** Constructor for derived types only */
|
||||
Region (Session& s, samplepos_t start, samplecnt_t length, const std::string& name, DataType);
|
||||
Region (Session& s, timepos_t start, timecnt_t length, const std::string& name, DataType);
|
||||
|
||||
virtual bool can_trim_start_before_source_start () const {
|
||||
return false;
|
||||
|
@ -406,25 +424,24 @@ protected:
|
|||
void send_change (const PBD::PropertyChange&);
|
||||
virtual int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal);
|
||||
void post_set (const PBD::PropertyChange&);
|
||||
virtual void set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
|
||||
virtual void set_position_music_internal (double qn);
|
||||
virtual void set_length_internal (samplecnt_t, const int32_t sub_num);
|
||||
virtual void set_start_internal (samplecnt_t, const int32_t sub_num = 0);
|
||||
bool verify_start_and_length (samplepos_t, samplecnt_t&);
|
||||
virtual void set_position_internal (timepos_t pos);
|
||||
virtual void set_length_internal (timecnt_t const &);
|
||||
virtual void set_start_internal (timecnt_t const &);
|
||||
bool verify_start_and_length (timecnt_t const &, timecnt_t&);
|
||||
void first_edit ();
|
||||
|
||||
DataType _type;
|
||||
|
||||
PBD::Property<bool> _sync_marked;
|
||||
PBD::Property<bool> _left_of_split;
|
||||
PBD::Property<bool> _right_of_split;
|
||||
PBD::Property<bool> _valid_transients;
|
||||
PBD::Property<samplepos_t> _start;
|
||||
PBD::Property<samplecnt_t> _length;
|
||||
PBD::Property<samplepos_t> _position;
|
||||
PBD::Property<double> _beat;
|
||||
PBD::Property<bool> _sync_marked;
|
||||
PBD::Property<bool> _left_of_split;
|
||||
PBD::Property<bool> _right_of_split;
|
||||
PBD::Property<bool> _valid_transients;
|
||||
PBD::Property<timecnt_t> _start;
|
||||
PBD::Property<timecnt_t> _length;
|
||||
PBD::Property<timepos_t> _position;
|
||||
PBD::Property<double> _beat;
|
||||
/** Sync position relative to the start of our file */
|
||||
PBD::Property<samplepos_t> _sync_position;
|
||||
PBD::Property<timecnt_t> _sync_position;
|
||||
|
||||
double _quarter_note;
|
||||
|
||||
|
@ -452,15 +469,15 @@ protected:
|
|||
private:
|
||||
void mid_thaw (const PBD::PropertyChange&);
|
||||
|
||||
virtual void trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num);
|
||||
void modify_front (samplepos_t new_position, bool reset_fade, const int32_t sub_num);
|
||||
void modify_end (samplepos_t new_position, bool reset_fade, const int32_t sub_num);
|
||||
virtual void trim_to_internal (timepos_t position, timecnt_t const & length);
|
||||
void modify_front (timepos_t new_position, bool reset_fade);
|
||||
void modify_end (timepos_t new_position, bool reset_fade);
|
||||
|
||||
void maybe_uncopy ();
|
||||
|
||||
bool verify_start (samplepos_t);
|
||||
bool verify_start_mutable (samplepos_t&_start);
|
||||
bool verify_length (samplecnt_t&);
|
||||
bool verify_start (timecnt_t const &);
|
||||
bool verify_start_mutable (timecnt_t&);
|
||||
bool verify_length (timecnt_t&);
|
||||
|
||||
virtual void recompute_at_start () = 0;
|
||||
virtual void recompute_at_end () = 0;
|
||||
|
@ -475,8 +492,8 @@ private:
|
|||
PBD::Property<bool> _external;
|
||||
PBD::Property<bool> _hidden;
|
||||
PBD::Property<bool> _position_locked;
|
||||
PBD::Property<samplepos_t> _ancestral_start;
|
||||
PBD::Property<samplecnt_t> _ancestral_length;
|
||||
PBD::Property<timecnt_t> _ancestral_start;
|
||||
PBD::Property<timecnt_t> _ancestral_length;
|
||||
PBD::Property<float> _stretch;
|
||||
PBD::Property<float> _shift;
|
||||
PBD::EnumProperty<PositionLockStyle> _position_lock_style;
|
||||
|
@ -484,8 +501,8 @@ private:
|
|||
PBD::Property<std::string> _tags;
|
||||
PBD::Property<bool> _contents; // type is irrelevant
|
||||
|
||||
samplecnt_t _last_length;
|
||||
samplepos_t _last_position;
|
||||
timecnt_t _last_length;
|
||||
timepos_t _last_position;
|
||||
mutable RegionEditState _first_edit;
|
||||
layer_t _layer;
|
||||
|
||||
|
|
|
@ -43,7 +43,9 @@
|
|||
#include <inttypes.h>
|
||||
|
||||
#include "temporal/bbt_time.h"
|
||||
#include "temporal/superclock.h"
|
||||
#include "temporal/time.h"
|
||||
#include "temporal/timeline.h"
|
||||
#include "temporal/types.h"
|
||||
|
||||
#include "pbd/id.h"
|
||||
|
@ -85,6 +87,10 @@ typedef Temporal::samplecnt_t samplecnt_t;
|
|||
typedef Temporal::samplepos_t samplepos_t;
|
||||
typedef Temporal::sampleoffset_t sampleoffset_t;
|
||||
|
||||
typedef Temporal::timepos_t timepos_t;
|
||||
typedef Temporal::timecnt_t timecnt_t;
|
||||
typedef Temporal::superclock_t superclock_t;
|
||||
|
||||
static const layer_t max_layer = UINT32_MAX;
|
||||
|
||||
// a set of (time) intervals: first of pair is the offset of the start within the region, second is the offset of the end
|
||||
|
|
|
@ -79,6 +79,61 @@ DEFINE_ENUM_CONVERT(ARDOUR::LoopFadeChoice)
|
|||
|
||||
DEFINE_ENUM_CONVERT(MusicalMode::Type)
|
||||
|
||||
template <>
|
||||
inline std::string to_string (ARDOUR::timepos_t val)
|
||||
{
|
||||
return val.to_string ();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline ARDOUR::timepos_t string_to (std::string const & str)
|
||||
{
|
||||
ARDOUR::timepos_t tmp;
|
||||
tmp.string_to (str);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool to_string (ARDOUR::timepos_t val, std::string & str)
|
||||
{
|
||||
str = val.to_string ();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool string_to (std::string const & str, ARDOUR::timepos_t & val)
|
||||
{
|
||||
return val.string_to (str);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
inline std::string to_string (ARDOUR::timecnt_t val)
|
||||
{
|
||||
return val.to_string ();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline ARDOUR::timecnt_t string_to (std::string const & str)
|
||||
{
|
||||
ARDOUR::timecnt_t tmp;
|
||||
tmp.string_to (str);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool to_string (ARDOUR::timecnt_t val, std::string & str)
|
||||
{
|
||||
str = val.to_string ();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool string_to (std::string const & str, ARDOUR::timecnt_t & val)
|
||||
{
|
||||
return val.string_to (str);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool to_string (ARDOUR::AutoState val, std::string& str)
|
||||
{
|
||||
|
|
|
@ -46,7 +46,7 @@ EBUr128Analysis::run (Readable* src)
|
|||
{
|
||||
int ret = -1;
|
||||
bool done = false;
|
||||
samplecnt_t len = src->readable_length();
|
||||
samplecnt_t len = src->readable_length_samples();
|
||||
samplepos_t pos = 0;
|
||||
uint32_t n_channels = src->n_channels();
|
||||
Plugin::FeatureSet features;
|
||||
|
|
|
@ -114,13 +114,13 @@ Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string regi
|
|||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*si);
|
||||
if (afs) {
|
||||
afs->done_with_peakfile_writes ();
|
||||
afs->update_header (region->position(), *now, xnow);
|
||||
afs->update_header (region->position_sample(), *now, xnow);
|
||||
afs->mark_immutable ();
|
||||
}
|
||||
|
||||
boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(*si);
|
||||
if (smfs) {
|
||||
smfs->set_natural_position (region->position());
|
||||
smfs->set_natural_position (region->position_sample());
|
||||
smfs->flush ();
|
||||
}
|
||||
|
||||
|
@ -139,10 +139,10 @@ Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string regi
|
|||
PropertyList plist;
|
||||
|
||||
plist.add (Properties::start, 0);
|
||||
plist.add (Properties::length, region->length());
|
||||
plist.add (Properties::length, region->nt_length());
|
||||
plist.add (Properties::name, region_name);
|
||||
plist.add (Properties::whole_file, true);
|
||||
plist.add (Properties::position, region->position());
|
||||
plist.add (Properties::position, region->nt_position());
|
||||
|
||||
boost::shared_ptr<Region> r = RegionFactory::create (nsrcs, plist);
|
||||
|
||||
|
|
|
@ -354,24 +354,6 @@ MidiRegion::set_position_internal (samplepos_t pos, bool allow_bbt_recompute, co
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegion::set_position_music_internal (double qn)
|
||||
{
|
||||
Region::set_position_music_internal (qn);
|
||||
/* set _start to new position in tempo map */
|
||||
_start = _session.tempo_map().samples_between_quarter_notes (quarter_note() - start_beats(), quarter_note());
|
||||
|
||||
if (position_lock_style() == AudioTime) {
|
||||
_length_beats = _session.tempo_map().quarter_note_at_sample (_position + _length) - quarter_note();
|
||||
|
||||
} else {
|
||||
/* leave _length_beats alone, and change _length to reflect the state of things
|
||||
at the new position (tempo map may dictate a different number of samples).
|
||||
*/
|
||||
_length = _session.tempo_map().samples_between_quarter_notes (quarter_note(), quarter_note() + length_beats());
|
||||
}
|
||||
}
|
||||
|
||||
samplecnt_t
|
||||
MidiRegion::read_at (Evoral::EventSink<samplepos_t>& out,
|
||||
samplepos_t position,
|
||||
|
|
|
@ -776,7 +776,9 @@ Playlist::add_region_internal (boost::shared_ptr<Region> region, samplepos_t pos
|
|||
boost::shared_ptr<Playlist> foo (shared_from_this ());
|
||||
region->set_playlist (boost::weak_ptr<Playlist> (foo));
|
||||
}
|
||||
|
||||
if (for_music) {
|
||||
#warning NUTEMPO FIXME need timepos_t here
|
||||
region->set_position_music (quarter_note);
|
||||
} else {
|
||||
region->set_position (position, sub_num);
|
||||
|
|
|
@ -84,11 +84,11 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
string::size_type at;
|
||||
|
||||
#ifndef NDEBUG
|
||||
cerr << "RBEffect: source region: position = " << region->position ()
|
||||
<< ", start = " << region->start ()
|
||||
<< ", length = " << region->length ()
|
||||
<< ", ancestral_start = " << region->ancestral_start ()
|
||||
<< ", ancestral_length = " << region->ancestral_length ()
|
||||
cerr << "RBEffect: source region: position = " << region->position_sample ()
|
||||
<< ", start = " << region->start_sample ()
|
||||
<< ", length = " << region->length_samples ()
|
||||
<< ", ancestral_start = " << region->ancestral_start_sample ()
|
||||
<< ", ancestral_length = " << region->ancestral_length_samples ()
|
||||
<< ", stretch " << region->stretch ()
|
||||
<< ", shift " << region->shift () << endl;
|
||||
#endif
|
||||
|
@ -151,11 +151,10 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
double stretch = region->stretch () * tsr.time_fraction;
|
||||
double shift = region->shift () * tsr.pitch_fraction;
|
||||
|
||||
samplecnt_t read_start = region->ancestral_start () +
|
||||
samplecnt_t (region->start () / (double)region->stretch ());
|
||||
samplecnt_t read_start = region->ancestral_start_sample () +
|
||||
samplecnt_t (region->start_sample () / (double)region->stretch ());
|
||||
|
||||
samplecnt_t read_duration =
|
||||
samplecnt_t (region->length () / (double)region->stretch ());
|
||||
samplecnt_t read_duration = samplecnt_t (region->length_samples () / (double)region->stretch ());
|
||||
|
||||
uint32_t channels = region->n_channels ();
|
||||
|
||||
|
@ -221,7 +220,7 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
|
||||
samplepos_t this_position;
|
||||
this_position = read_start + pos -
|
||||
region->start () + region->position ();
|
||||
region->start_sample () + region->position_sample ();
|
||||
|
||||
this_read = region->master_read_at (buffers[i],
|
||||
buffers[i],
|
||||
|
@ -258,7 +257,7 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
|
||||
samplepos_t this_position;
|
||||
this_position = read_start + pos -
|
||||
region->start () + region->position ();
|
||||
region->start_sample () + region->position_sample ();
|
||||
|
||||
this_read = region->master_read_at (buffers[i],
|
||||
buffers[i],
|
||||
|
@ -269,7 +268,7 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
|
||||
if (this_read != this_time) {
|
||||
error << string_compose (_("tempoize: error reading data from %1 at %2 (wanted %3, got %4)"),
|
||||
region->name (), pos + region->position (), this_time, this_read)
|
||||
region->name (), pos + region->position_sample (), this_time, this_read)
|
||||
<< endmsg;
|
||||
goto out;
|
||||
}
|
||||
|
@ -353,15 +352,16 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
/* now reset ancestral data for each new region */
|
||||
|
||||
for (vector<boost::shared_ptr<Region> >::iterator x = results.begin (); x != results.end (); ++x) {
|
||||
(*x)->set_ancestral_data (read_start,
|
||||
read_duration,
|
||||
(*x)->set_ancestral_data (timecnt_t (read_start, timepos_t()),
|
||||
timecnt_t (read_duration, read_start),
|
||||
stretch,
|
||||
shift);
|
||||
(*x)->set_master_sources (region->master_sources ());
|
||||
/* multiply the old (possibly previously stretched) region length by the extra
|
||||
* stretch this time around to get its new length. this is a non-music based edit atm.
|
||||
*/
|
||||
(*x)->set_length ((*x)->length () * tsr.time_fraction, 0);
|
||||
#warning NUTEMPO FIXME should use (*x)->position() sa 2nd arg also needs to figure out units for first arg
|
||||
(*x)->set_length (timecnt_t (samplepos_t ((*x)->length_samples () * tsr.time_fraction), (*x)->position_samples()));
|
||||
}
|
||||
|
||||
/* stretch region gain envelope */
|
||||
|
|
|
@ -69,14 +69,14 @@ namespace ARDOUR {
|
|||
PBD::PropertyDescriptor<bool> hidden;
|
||||
PBD::PropertyDescriptor<bool> position_locked;
|
||||
PBD::PropertyDescriptor<bool> valid_transients;
|
||||
PBD::PropertyDescriptor<samplepos_t> start;
|
||||
PBD::PropertyDescriptor<samplecnt_t> length;
|
||||
PBD::PropertyDescriptor<samplepos_t> position;
|
||||
PBD::PropertyDescriptor<timecnt_t> start;
|
||||
PBD::PropertyDescriptor<timecnt_t> length;
|
||||
PBD::PropertyDescriptor<timepos_t> position;
|
||||
PBD::PropertyDescriptor<double> beat;
|
||||
PBD::PropertyDescriptor<samplecnt_t> sync_position;
|
||||
PBD::PropertyDescriptor<timecnt_t> sync_position;
|
||||
PBD::PropertyDescriptor<layer_t> layer;
|
||||
PBD::PropertyDescriptor<samplepos_t> ancestral_start;
|
||||
PBD::PropertyDescriptor<samplecnt_t> ancestral_length;
|
||||
PBD::PropertyDescriptor<timecnt_t> ancestral_start;
|
||||
PBD::PropertyDescriptor<timecnt_t> ancestral_length;
|
||||
PBD::PropertyDescriptor<float> stretch;
|
||||
PBD::PropertyDescriptor<float> shift;
|
||||
PBD::PropertyDescriptor<PositionLockStyle> position_lock_style;
|
||||
|
@ -188,11 +188,11 @@ 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)) \
|
||||
, _position (Properties::position, 0) \
|
||||
, _start (Properties::start, timecnt_t (s, _type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))) \
|
||||
, _length (Properties::length, timecnt_t (l,timepos_t (s))) \
|
||||
, _position (Properties::position, _type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0))) \
|
||||
, _beat (Properties::beat, 0.0) \
|
||||
, _sync_position (Properties::sync_position, (s)) \
|
||||
, _sync_position (Properties::sync_position, timecnt_t (s, _type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))) \
|
||||
, _quarter_note (0.0) \
|
||||
, _transient_user_start (0) \
|
||||
, _transient_analysis_start (0) \
|
||||
|
@ -208,7 +208,7 @@ Region::register_properties ()
|
|||
, _external (Properties::external, false) \
|
||||
, _hidden (Properties::hidden, false) \
|
||||
, _position_locked (Properties::position_locked, false) \
|
||||
, _ancestral_start (Properties::ancestral_start, (s)) \
|
||||
, _ancestral_start (Properties::ancestral_start, timecnt_t (s, _type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))) \
|
||||
, _ancestral_length (Properties::ancestral_length, (l)) \
|
||||
, _stretch (Properties::stretch, 1.0) \
|
||||
, _shift (Properties::shift, 1.0) \
|
||||
|
@ -254,12 +254,12 @@ Region::register_properties ()
|
|||
, _contents (Properties::contents, other->_contents)
|
||||
|
||||
/* derived-from-derived constructor (no sources in constructor) */
|
||||
Region::Region (Session& s, samplepos_t start, samplecnt_t length, const string& name, DataType type)
|
||||
Region::Region (Session& s, timepos_t start, timecnt_t length, const string& name, DataType type)
|
||||
: SessionObject(s, name)
|
||||
, _type(type)
|
||||
, REGION_DEFAULT_STATE(start,length)
|
||||
, _last_length (length)
|
||||
, _last_position (0)
|
||||
, _last_position (_type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))
|
||||
, _first_edit (EditChangesNothing)
|
||||
, _layer (0)
|
||||
, _changemap (0)
|
||||
|
@ -273,9 +273,10 @@ Region::Region (Session& s, samplepos_t start, samplecnt_t length, const string&
|
|||
Region::Region (const SourceList& srcs)
|
||||
: SessionObject(srcs.front()->session(), "toBeRenamed")
|
||||
, _type (srcs.front()->type())
|
||||
, REGION_DEFAULT_STATE(0,0)
|
||||
, _last_length (0)
|
||||
, _last_position (0)
|
||||
, REGION_DEFAULT_STATE(_type == DataType::MIDI ? timecnt_t (Temporal::Beats()) : timecnt_t (superclock_t(0)),
|
||||
_type == DataType::MIDI ? timecnt_t (Temporal::Beats()) : timecnt_t (superclock_t (0)))
|
||||
, _last_length (_type == DataType::MIDI ? timecnt_t (Temporal::Beats()) : timecnt_t (superclock_t (0)))
|
||||
, _last_position (_type == DataType::MIDI ? timepos_t (Temporal::Beats()) : timepos_t (superclock_t (0)))
|
||||
, _first_edit (EditChangesNothing)
|
||||
, _layer (0)
|
||||
, _changemap (0)
|
||||
|
@ -354,7 +355,7 @@ Region::Region (boost::shared_ptr<const Region> other)
|
|||
* 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()
|
||||
*/
|
||||
Region::Region (boost::shared_ptr<const Region> other, MusicSample offset)
|
||||
Region::Region (boost::shared_ptr<const Region> other, timecnt_t offset)
|
||||
: SessionObject(other->session(), other->name())
|
||||
, _type (other->data_type())
|
||||
, REGION_COPY_STATE (other)
|
||||
|
@ -376,19 +377,8 @@ Region::Region (boost::shared_ptr<const Region> other, MusicSample offset)
|
|||
use_sources (other->_sources);
|
||||
set_master_sources (other->_master_sources);
|
||||
|
||||
_position = other->_position + offset.sample;
|
||||
_start = other->_start + offset.sample;
|
||||
|
||||
/* prevent offset of 0 from altering musical position */
|
||||
if (offset.sample != 0) {
|
||||
const double offset_qn = _session.tempo_map().exact_qn_at_sample (other->_position + offset.sample, offset.division)
|
||||
- other->_quarter_note;
|
||||
|
||||
_quarter_note = other->_quarter_note + offset_qn;
|
||||
_beat = _session.tempo_map().beat_at_quarter_note (_quarter_note);
|
||||
} else {
|
||||
_quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
|
||||
}
|
||||
_position = other->_position.val() + offset;
|
||||
_start = other->_start.val() + offset;
|
||||
|
||||
/* if the other region had a distinct sync point
|
||||
* set, then continue to use it as best we can.
|
||||
|
@ -482,29 +472,31 @@ Region::set_selected_for_solo(bool yn)
|
|||
}
|
||||
|
||||
void
|
||||
Region::set_length (samplecnt_t len, const int32_t sub_num)
|
||||
Region::set_length (timecnt_t const & len)
|
||||
{
|
||||
//cerr << "Region::set_length() len = " << len << endl;
|
||||
if (locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_length != len && len != 0) {
|
||||
if (_length != len && !len.zero()) {
|
||||
|
||||
/* check that the current _position wouldn't make the new
|
||||
* length impossible.
|
||||
*/
|
||||
|
||||
if (max_samplepos - len < _position) {
|
||||
if (timepos_t::max().earlier (len) < _position) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!verify_length (len)) {
|
||||
timecnt_t l = len;
|
||||
|
||||
if (!verify_length (l)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
set_length_internal (len, sub_num);
|
||||
set_length_internal (l);
|
||||
_whole_file = false;
|
||||
first_edit ();
|
||||
maybe_uncopy ();
|
||||
|
@ -519,7 +511,7 @@ Region::set_length (samplecnt_t len, const int32_t sub_num)
|
|||
}
|
||||
|
||||
void
|
||||
Region::set_length_internal (samplecnt_t len, const int32_t sub_num)
|
||||
Region::set_length_internal (timecnt_t const & len)
|
||||
{
|
||||
_last_length = _length;
|
||||
_length = len;
|
||||
|
@ -559,7 +551,7 @@ Region::at_natural_position () const
|
|||
boost::shared_ptr<Region> whole_file_region = get_parent();
|
||||
|
||||
if (whole_file_region) {
|
||||
if (_position == whole_file_region->position() + _start) {
|
||||
if (_position == whole_file_region->nt_position() + _start) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -579,12 +571,12 @@ Region::move_to_natural_position ()
|
|||
boost::shared_ptr<Region> whole_file_region = get_parent();
|
||||
|
||||
if (whole_file_region) {
|
||||
set_position (whole_file_region->position() + _start);
|
||||
set_position (whole_file_region->nt_position() + _start);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Region::special_set_position (samplepos_t pos)
|
||||
Region::special_set_position (timepos_t pos)
|
||||
{
|
||||
/* this is used when creating a whole file region as
|
||||
* a way to store its "natural" or "captured" position.
|
||||
|
@ -615,17 +607,10 @@ Region::update_after_tempo_map_change (bool send)
|
|||
return;
|
||||
}
|
||||
|
||||
if (_position_lock_style == AudioTime) {
|
||||
/* don't signal as the actual position has not chnged */
|
||||
recompute_position_from_lock_style (0);
|
||||
if (_position.val().time_domain() == Temporal::AudioTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* prevent movement before 0 */
|
||||
const samplepos_t pos = max ((samplepos_t) 0, _session.tempo_map().sample_at_beat (_beat));
|
||||
/* we have _beat. update sample position non-musically */
|
||||
set_position_internal (pos, false, 0);
|
||||
|
||||
/* do this even if the position is the same. this helps out
|
||||
* a GUI that has moved its representation already.
|
||||
*/
|
||||
|
@ -636,7 +621,7 @@ Region::update_after_tempo_map_change (bool send)
|
|||
}
|
||||
|
||||
void
|
||||
Region::set_position (samplepos_t pos, int32_t sub_num)
|
||||
Region::set_position (timepos_t pos)
|
||||
{
|
||||
if (!can_move()) {
|
||||
return;
|
||||
|
@ -649,18 +634,16 @@ Region::set_position (samplepos_t pos, int32_t sub_num)
|
|||
|
||||
p_and_l.add (Properties::position);
|
||||
|
||||
if (position_lock_style() == AudioTime) {
|
||||
set_position_internal (pos, true, sub_num);
|
||||
} else {
|
||||
if (!_session.loading()) {
|
||||
_beat = _session.tempo_map().exact_beat_at_sample (pos, sub_num);
|
||||
_quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
|
||||
}
|
||||
set_position_internal (pos);
|
||||
|
||||
set_position_internal (pos, false, sub_num);
|
||||
}
|
||||
/* if locked to beats or bbt, changing position can potentially change
|
||||
* the length, because the tempo map may differ at the two different
|
||||
* positions. Theoretically we could check this, but the cost of
|
||||
* notifying about a (potential) length change is not that expensive
|
||||
* given that we already are notifying about position change.
|
||||
*/
|
||||
|
||||
if (position_lock_style() == MusicTime) {
|
||||
if (position_lock_style() != AudioTime) {
|
||||
p_and_l.add (Properties::length);
|
||||
}
|
||||
|
||||
|
@ -669,85 +652,28 @@ Region::set_position (samplepos_t pos, int32_t sub_num)
|
|||
}
|
||||
|
||||
void
|
||||
Region::set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num)
|
||||
Region::set_position_internal (timepos_t pos)
|
||||
{
|
||||
/* 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;
|
||||
_last_length.set_position (_position);
|
||||
|
||||
if (_position != pos) {
|
||||
_position = pos;
|
||||
|
||||
if (allow_bbt_recompute) {
|
||||
recompute_position_from_lock_style (sub_num);
|
||||
} else {
|
||||
/* MusicTime dictates that we glue to ardour beats. the pulse may have changed.*/
|
||||
_quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
|
||||
}
|
||||
_start.call().set_position (pos);
|
||||
_length.call().set_position (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 (max_samplepos - _length < _position) {
|
||||
if (timepos_t::max().earlier (_length) < _position) {
|
||||
_last_length = _length;
|
||||
_length = max_samplepos - _position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Region::set_position_music (double qn)
|
||||
{
|
||||
if (!can_move()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* do this even if the position is the same. this helps out
|
||||
* a GUI that has moved its representation already.
|
||||
*/
|
||||
PropertyChange p_and_l;
|
||||
|
||||
p_and_l.add (Properties::position);
|
||||
|
||||
if (!_session.loading()) {
|
||||
_beat = _session.tempo_map().beat_at_quarter_note (qn);
|
||||
}
|
||||
|
||||
/* will set sample accordingly */
|
||||
set_position_music_internal (qn);
|
||||
|
||||
if (position_lock_style() == MusicTime) {
|
||||
p_and_l.add (Properties::length);
|
||||
}
|
||||
|
||||
send_change (p_and_l);
|
||||
}
|
||||
|
||||
void
|
||||
Region::set_position_music_internal (double qn)
|
||||
{
|
||||
/* 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 (_quarter_note != qn) {
|
||||
_position = _session.tempo_map().sample_at_quarter_note (qn);
|
||||
_quarter_note = qn;
|
||||
|
||||
/* 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 (max_samplepos - _length < _position) {
|
||||
_last_length = _length;
|
||||
_length = max_samplepos - _position;
|
||||
_length = _position.call().distance (timepos_t::max());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -758,7 +684,7 @@ Region::set_position_music_internal (double qn)
|
|||
* _last_position to prevent an implied move.
|
||||
*/
|
||||
void
|
||||
Region::set_initial_position (samplepos_t pos)
|
||||
Region::set_initial_position (timepos_t pos)
|
||||
{
|
||||
if (!can_move()) {
|
||||
return;
|
||||
|
@ -773,14 +699,15 @@ Region::set_initial_position (samplepos_t pos)
|
|||
* XXX is this the right thing to do?
|
||||
*/
|
||||
|
||||
if (max_samplepos - _length < _position) {
|
||||
if (timepos_t::max().earlier (_length) < _position) {
|
||||
_last_length = _length;
|
||||
_length = max_samplepos - _position;
|
||||
_length = _position.call().distance (timepos_t::max());
|
||||
}
|
||||
|
||||
recompute_position_from_lock_style (0);
|
||||
recompute_position_from_lock_style ();
|
||||
/* ensure that this move doesn't cause a range move */
|
||||
_last_position = _position;
|
||||
_last_length.set_position (_position);
|
||||
}
|
||||
|
||||
|
||||
|
@ -791,46 +718,48 @@ Region::set_initial_position (samplepos_t pos)
|
|||
}
|
||||
|
||||
void
|
||||
Region::recompute_position_from_lock_style (const int32_t sub_num)
|
||||
Region::recompute_position_from_lock_style ()
|
||||
{
|
||||
_beat = _session.tempo_map().exact_beat_at_sample (_position, sub_num);
|
||||
_quarter_note = _session.tempo_map().exact_qn_at_sample (_position, sub_num);
|
||||
/* XXX currently do nothing, but if we wanted to reduce lazy evaluation
|
||||
* of timepos_t non-canonical values, we could possibly do it here.
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
Region::nudge_position (sampleoffset_t n)
|
||||
Region::nudge_position (timecnt_t const & n)
|
||||
{
|
||||
if (locked() || video_locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
if (n.zero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
samplepos_t new_position = _position;
|
||||
timepos_t new_position = _position;
|
||||
|
||||
if (n > 0) {
|
||||
if (_position > max_samplepos - n) {
|
||||
new_position = max_samplepos;
|
||||
if (n.positive()) {
|
||||
if (nt_position() > timepos_t::max().earlier (n)) {
|
||||
new_position = timepos_t::max();
|
||||
} else {
|
||||
new_position += n;
|
||||
}
|
||||
} else {
|
||||
if (_position < -n) {
|
||||
if (nt_position() < -n) {
|
||||
new_position = 0;
|
||||
} else {
|
||||
new_position += n;
|
||||
}
|
||||
}
|
||||
|
||||
/* assumes non-musical nudge */
|
||||
set_position_internal (new_position, true, 0);
|
||||
set_position_internal (new_position);
|
||||
|
||||
send_change (Properties::position);
|
||||
}
|
||||
|
||||
void
|
||||
Region::set_ancestral_data (samplepos_t s, samplecnt_t l, float st, float sh)
|
||||
Region::set_ancestral_data (timecnt_t const & s, timecnt_t const & l, float st, float sh)
|
||||
{
|
||||
_ancestral_length = l;
|
||||
_ancestral_start = s;
|
||||
|
@ -839,7 +768,7 @@ Region::set_ancestral_data (samplepos_t s, samplecnt_t l, float st, float sh)
|
|||
}
|
||||
|
||||
void
|
||||
Region::set_start (samplepos_t pos)
|
||||
Region::set_start (timecnt_t const & pos)
|
||||
{
|
||||
if (locked() || position_locked() || video_locked()) {
|
||||
return;
|
||||
|
@ -851,11 +780,13 @@ Region::set_start (samplepos_t pos)
|
|||
|
||||
if (_start != pos) {
|
||||
|
||||
if (!verify_start (pos)) {
|
||||
timecnt_t p = pos;
|
||||
|
||||
if (!verify_start (p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_start_internal (pos);
|
||||
set_start_internal (p);
|
||||
_whole_file = false;
|
||||
first_edit ();
|
||||
maybe_invalidate_transients ();
|
||||
|
@ -865,43 +796,40 @@ Region::set_start (samplepos_t pos)
|
|||
}
|
||||
|
||||
void
|
||||
Region::move_start (sampleoffset_t distance, const int32_t sub_num)
|
||||
Region::move_start (timecnt_t const & distance)
|
||||
{
|
||||
if (locked() || position_locked() || video_locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
samplepos_t new_start;
|
||||
timecnt_t new_start (_start);
|
||||
|
||||
if (distance > 0) {
|
||||
if (distance.positive()) {
|
||||
|
||||
if (_start > max_samplepos - distance) {
|
||||
new_start = max_samplepos; // makes no sense
|
||||
if (_start > timecnt_t::max() - distance) {
|
||||
new_start = timecnt_t::max(); // makes no sense
|
||||
} else {
|
||||
new_start = _start + distance;
|
||||
new_start = nt_start() + distance;
|
||||
}
|
||||
|
||||
if (!verify_start (new_start)) {
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (distance < 0) {
|
||||
} else {
|
||||
|
||||
if (_start < -distance) {
|
||||
new_start = 0;
|
||||
} else {
|
||||
new_start = _start + distance;
|
||||
new_start = nt_start() + distance;
|
||||
}
|
||||
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_start == _start) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_start_internal (new_start, sub_num);
|
||||
set_start_internal (new_start);
|
||||
|
||||
_whole_file = false;
|
||||
first_edit ();
|
||||
|
@ -910,55 +838,56 @@ Region::move_start (sampleoffset_t distance, const int32_t sub_num)
|
|||
}
|
||||
|
||||
void
|
||||
Region::trim_front (samplepos_t new_position, const int32_t sub_num)
|
||||
Region::trim_front (timepos_t new_position)
|
||||
{
|
||||
modify_front (new_position, false, sub_num);
|
||||
modify_front (new_position, false);
|
||||
}
|
||||
|
||||
void
|
||||
Region::cut_front (samplepos_t new_position, const int32_t sub_num)
|
||||
Region::cut_front (timepos_t new_position)
|
||||
{
|
||||
modify_front (new_position, true, sub_num);
|
||||
modify_front (new_position, true);
|
||||
}
|
||||
|
||||
void
|
||||
Region::cut_end (samplepos_t new_endpoint, const int32_t sub_num)
|
||||
Region::cut_end (timepos_t new_endpoint)
|
||||
{
|
||||
modify_end (new_endpoint, true, sub_num);
|
||||
modify_end (new_endpoint, true);
|
||||
}
|
||||
|
||||
void
|
||||
Region::modify_front (samplepos_t new_position, bool reset_fade, const int32_t sub_num)
|
||||
Region::modify_front (timepos_t new_position, bool reset_fade)
|
||||
{
|
||||
if (locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
samplepos_t end = last_sample();
|
||||
samplepos_t source_zero;
|
||||
timepos_t end = nt_end().decrement();
|
||||
timepos_t source_zero;
|
||||
|
||||
if (_position > _start) {
|
||||
source_zero = _position - _start;
|
||||
if (nt_position() > nt_start()) {
|
||||
source_zero = source_position ();
|
||||
} else {
|
||||
source_zero = 0; // its actually negative, but this will work for us
|
||||
}
|
||||
|
||||
if (new_position < end) { /* can't trim it zero or negative length */
|
||||
|
||||
samplecnt_t newlen = 0;
|
||||
timecnt_t newlen (_length);
|
||||
timepos_t np = new_position;
|
||||
|
||||
if (!can_trim_start_before_source_start ()) {
|
||||
/* can't trim it back past where source position zero is located */
|
||||
new_position = max (new_position, source_zero);
|
||||
np = max (np, source_zero);
|
||||
}
|
||||
|
||||
if (new_position > _position) {
|
||||
newlen = _length - (new_position - _position);
|
||||
if (np > nt_position()) {
|
||||
newlen = nt_length() - (nt_position().distance (np));
|
||||
} else {
|
||||
newlen = _length + (_position - new_position);
|
||||
newlen = nt_length() + (np.distance (nt_position()));
|
||||
}
|
||||
|
||||
trim_to_internal (new_position, newlen, sub_num);
|
||||
trim_to_internal (np, newlen);
|
||||
|
||||
if (reset_fade) {
|
||||
_right_of_split = true;
|
||||
|
@ -973,14 +902,14 @@ Region::modify_front (samplepos_t new_position, bool reset_fade, const int32_t s
|
|||
}
|
||||
|
||||
void
|
||||
Region::modify_end (samplepos_t new_endpoint, bool reset_fade, const int32_t sub_num)
|
||||
Region::modify_end (timepos_t new_endpoint, bool reset_fade)
|
||||
{
|
||||
if (locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (new_endpoint > _position) {
|
||||
trim_to_internal (_position, new_endpoint - _position, sub_num);
|
||||
trim_to_internal (_position, nt_position().distance (new_endpoint));
|
||||
if (reset_fade) {
|
||||
_left_of_split = true;
|
||||
}
|
||||
|
@ -994,19 +923,19 @@ Region::modify_end (samplepos_t new_endpoint, bool reset_fade, const int32_t sub
|
|||
* a region at 0 of length 10 has an endpoint of 9.
|
||||
*/
|
||||
void
|
||||
Region::trim_end (samplepos_t new_endpoint, const int32_t sub_num)
|
||||
Region::trim_end (timepos_t new_endpoint)
|
||||
{
|
||||
modify_end (new_endpoint, false, sub_num);
|
||||
modify_end (new_endpoint, false);
|
||||
}
|
||||
|
||||
void
|
||||
Region::trim_to (samplepos_t position, samplecnt_t length, const int32_t sub_num)
|
||||
Region::trim_to (timepos_t position, timecnt_t const & length)
|
||||
{
|
||||
if (locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
trim_to_internal (position, length, sub_num);
|
||||
trim_to_internal (position, length);
|
||||
|
||||
if (!property_changes_suspended()) {
|
||||
recompute_at_start ();
|
||||
|
@ -1015,48 +944,50 @@ Region::trim_to (samplepos_t position, samplecnt_t length, const int32_t sub_num
|
|||
}
|
||||
|
||||
void
|
||||
Region::trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num)
|
||||
Region::trim_to_internal (timepos_t position, timecnt_t const & length)
|
||||
{
|
||||
samplepos_t new_start;
|
||||
timecnt_t new_start;
|
||||
|
||||
if (locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
sampleoffset_t const start_shift = position - _position;
|
||||
timecnt_t const start_shift = nt_position().distance (position);
|
||||
|
||||
if (start_shift > 0) {
|
||||
if (start_shift.positive()) {
|
||||
|
||||
if (_start > max_samplepos - start_shift) {
|
||||
new_start = max_samplepos;
|
||||
if (nt_start() > timecnt_t::max() - start_shift) {
|
||||
new_start = timecnt_t::max();
|
||||
} else {
|
||||
new_start = _start + start_shift;
|
||||
new_start = nt_start() + start_shift;
|
||||
}
|
||||
|
||||
} else if (start_shift < 0) {
|
||||
} else if (start_shift.negative()) {
|
||||
|
||||
if (_start < -start_shift && !can_trim_start_before_source_start ()) {
|
||||
if (nt_start() < -start_shift && !can_trim_start_before_source_start ()) {
|
||||
new_start = 0;
|
||||
} else {
|
||||
new_start = _start + start_shift;
|
||||
new_start = nt_start() + start_shift;
|
||||
}
|
||||
|
||||
} else {
|
||||
new_start = _start;
|
||||
new_start = nt_start();
|
||||
}
|
||||
|
||||
if (!verify_start_and_length (new_start, length)) {
|
||||
timecnt_t ns = new_start;
|
||||
timecnt_t nl = length;
|
||||
|
||||
if (!verify_start_and_length (ns, nl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PropertyChange what_changed;
|
||||
|
||||
if (_start != new_start) {
|
||||
set_start_internal (new_start, sub_num);
|
||||
if (nt_start() != ns) {
|
||||
set_start_internal (ns);
|
||||
what_changed.add (Properties::start);
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
|
@ -1065,19 +996,19 @@ Region::trim_to_internal (samplepos_t position, samplecnt_t length, const int32_
|
|||
* straddles a tempo/meter change.
|
||||
*/
|
||||
|
||||
if (_position != position) {
|
||||
if (nt_position() != position) {
|
||||
if (!property_changes_suspended()) {
|
||||
_last_position = _position;
|
||||
}
|
||||
set_position_internal (position, true, sub_num);
|
||||
set_position_internal (position);
|
||||
what_changed.add (Properties::position);
|
||||
}
|
||||
|
||||
if (_length != length) {
|
||||
if (nt_length() != nl) {
|
||||
if (!property_changes_suspended()) {
|
||||
_last_length = _length;
|
||||
}
|
||||
set_length_internal (length, sub_num);
|
||||
set_length_internal (nl);
|
||||
what_changed.add (Properties::length);
|
||||
}
|
||||
|
||||
|
@ -1169,10 +1100,10 @@ Region::set_position_locked (bool yn)
|
|||
* @param absolute_pos Session time.
|
||||
*/
|
||||
void
|
||||
Region::set_sync_position (samplepos_t absolute_pos)
|
||||
Region::set_sync_position (timepos_t absolute_pos)
|
||||
{
|
||||
/* position within our file */
|
||||
samplepos_t const file_pos = _start + (absolute_pos - _position);
|
||||
const timecnt_t file_pos = nt_start() + nt_position().distance (absolute_pos);
|
||||
|
||||
if (file_pos != _sync_position) {
|
||||
_sync_marked = true;
|
||||
|
@ -1199,7 +1130,7 @@ Region::clear_sync_position ()
|
|||
}
|
||||
|
||||
/* @return the sync point relative the first sample of the region */
|
||||
sampleoffset_t
|
||||
timecnt_t
|
||||
Region::sync_offset (int& dir) const
|
||||
{
|
||||
if (sync_marked()) {
|
||||
|
@ -1212,42 +1143,43 @@ Region::sync_offset (int& dir) const
|
|||
}
|
||||
} else {
|
||||
dir = 0;
|
||||
return 0;
|
||||
return timecnt_t ();
|
||||
}
|
||||
}
|
||||
|
||||
samplepos_t
|
||||
Region::adjust_to_sync (samplepos_t pos) const
|
||||
timepos_t
|
||||
Region::adjust_to_sync (timepos_t pos) const
|
||||
{
|
||||
int sync_dir;
|
||||
sampleoffset_t offset = sync_offset (sync_dir);
|
||||
timepos_t p = pos;
|
||||
timecnt_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;
|
||||
p.shift_earlier (offset);
|
||||
} else {
|
||||
pos = 0;
|
||||
p = 0;
|
||||
}
|
||||
} else {
|
||||
if (max_samplepos - pos > offset) {
|
||||
pos += offset;
|
||||
if (timepos_t::max().earlier (timecnt_t (p, p)) > offset) {
|
||||
p += offset;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
return p;
|
||||
}
|
||||
|
||||
/** @return Sync position in session time */
|
||||
samplepos_t
|
||||
timepos_t
|
||||
Region::sync_position() const
|
||||
{
|
||||
if (sync_marked()) {
|
||||
return _position - _start + _sync_position;
|
||||
return source_position() + _sync_position;
|
||||
} else {
|
||||
/* if sync has not been marked, use the start of the region */
|
||||
return _position;
|
||||
return nt_position();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1409,8 +1341,9 @@ Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_c
|
|||
*/
|
||||
|
||||
if (!_sources.empty() && _type == DataType::AUDIO) {
|
||||
if (_length > _sources.front()->length(_position)) {
|
||||
_length = _sources.front()->length(_position) - _start;
|
||||
if ((nt_length().time_domain() == Temporal::AudioTime) && (length_samples() > _sources.front()->length(position_sample()))) {
|
||||
#warning NUTEMPO FIXME do this better
|
||||
//_length = Temporal::samples_to_superclock (_sources.front()->length(position_sample()) - start_sample(), Temporal::_thread_sample_rate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1424,7 +1357,7 @@ Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_c
|
|||
&bbt_time.beats,
|
||||
&bbt_time.ticks) != 3) {
|
||||
_position_lock_style = AudioTime;
|
||||
_beat = _session.tempo_map().beat_at_sample (_position);
|
||||
_beat = _session.tempo_map().beat_at_sample (position_sample());
|
||||
} else {
|
||||
_beat = _session.tempo_map().beat_at_bbt (bbt_time);
|
||||
}
|
||||
|
@ -1745,20 +1678,23 @@ samplecnt_t
|
|||
Region::source_length(uint32_t n) const
|
||||
{
|
||||
assert (n < _sources.size());
|
||||
return _sources[n]->length (_position - _start);
|
||||
#warning NUTEMPO FIXME needs Source to use timeline types
|
||||
// return _sources[n]->length (_position - _start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Region::verify_length (samplecnt_t& len)
|
||||
Region::verify_length (timecnt_t& len)
|
||||
{
|
||||
if (source() && source()->length_mutable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
samplecnt_t maxlen = 0;
|
||||
timecnt_t maxlen;
|
||||
|
||||
for (uint32_t n = 0; n < _sources.size(); ++n) {
|
||||
maxlen = max (maxlen, source_length(n) - _start);
|
||||
#warning NUTEMPO FIXME source needs timeline types
|
||||
// maxlen = max (maxlen, source_length(n) - _start);
|
||||
}
|
||||
|
||||
len = min (len, maxlen);
|
||||
|
@ -1767,16 +1703,17 @@ Region::verify_length (samplecnt_t& len)
|
|||
}
|
||||
|
||||
bool
|
||||
Region::verify_start_and_length (samplepos_t new_start, samplecnt_t& new_length)
|
||||
Region::verify_start_and_length (timecnt_t const & new_start, timecnt_t& new_length)
|
||||
{
|
||||
if (source() && source()->length_mutable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
samplecnt_t maxlen = 0;
|
||||
timecnt_t maxlen;
|
||||
|
||||
for (uint32_t n = 0; n < _sources.size(); ++n) {
|
||||
maxlen = max (maxlen, source_length(n) - new_start);
|
||||
#warning NUTEMPO FIXME source needs timeline types
|
||||
// maxlen = max (maxlen, source_length(n) - new_start);
|
||||
}
|
||||
|
||||
new_length = min (new_length, maxlen);
|
||||
|
@ -1785,31 +1722,33 @@ Region::verify_start_and_length (samplepos_t new_start, samplecnt_t& new_length)
|
|||
}
|
||||
|
||||
bool
|
||||
Region::verify_start (samplepos_t pos)
|
||||
Region::verify_start (timecnt_t const & pos)
|
||||
{
|
||||
if (source() && source()->length_mutable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t n = 0; n < _sources.size(); ++n) {
|
||||
if (pos > source_length(n) - _length) {
|
||||
return false;
|
||||
}
|
||||
#warning NUTEMPO FIXME source needs timeline types
|
||||
// if (pos > source_length(n) - _length) {
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Region::verify_start_mutable (samplepos_t& new_start)
|
||||
Region::verify_start_mutable (timecnt_t & new_start)
|
||||
{
|
||||
if (source() && source()->length_mutable()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t n = 0; n < _sources.size(); ++n) {
|
||||
if (new_start > source_length(n) - _length) {
|
||||
new_start = source_length(n) - _length;
|
||||
}
|
||||
#warning NUTEMPO FIXME source needs timeline types
|
||||
// if (new_start > source_length(n) - _length) {
|
||||
// new_start = source_length(n) - _length;
|
||||
// }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1855,8 +1794,8 @@ Region::transients (AnalysisFeatureList& afl)
|
|||
{
|
||||
int cnt = afl.empty() ? 0 : 1;
|
||||
|
||||
Region::merge_features (afl, _onsets, _position);
|
||||
Region::merge_features (afl, _user_transients, _position + _transient_user_start - _start);
|
||||
Region::merge_features (afl, _onsets, position_sample());
|
||||
Region::merge_features (afl, _user_transients, position_sample() + _transient_user_start - start_sample());
|
||||
if (!_onsets.empty ()) {
|
||||
++cnt;
|
||||
}
|
||||
|
@ -2000,14 +1939,15 @@ Region::can_trim () const
|
|||
|
||||
ct = CanTrim (ct | FrontTrimLater | EndTrimEarlier);
|
||||
|
||||
if (start() != 0 || can_trim_start_before_source_start ()) {
|
||||
if (nt_start() != 0 || can_trim_start_before_source_start ()) {
|
||||
ct = CanTrim (ct | FrontTrimEarlier);
|
||||
}
|
||||
|
||||
if (!_sources.empty()) {
|
||||
if ((start() + length()) < _sources.front()->length (0)) {
|
||||
ct = CanTrim (ct | EndTrimLater);
|
||||
}
|
||||
#warning NUTEMPO FIXME source needs timeline types
|
||||
//if ((nt_start() + nt_length()) < _sources.front()->length (0)) {
|
||||
// ct = CanTrim (ct | EndTrimLater);
|
||||
//}
|
||||
}
|
||||
|
||||
return ct;
|
||||
|
@ -2038,18 +1978,18 @@ Region::post_set (const PropertyChange& pc)
|
|||
}
|
||||
|
||||
void
|
||||
Region::set_start_internal (samplecnt_t s, const int32_t sub_num)
|
||||
Region::set_start_internal (timecnt_t const & s)
|
||||
{
|
||||
_start = s;
|
||||
}
|
||||
|
||||
samplepos_t
|
||||
timepos_t
|
||||
Region::earliest_possible_position () const
|
||||
{
|
||||
if (_start > _position) {
|
||||
if (nt_start() > timecnt_t (_position, timepos_t())) {
|
||||
return 0;
|
||||
} else {
|
||||
return _position - _start;
|
||||
return source_position();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2062,12 +2002,32 @@ Region::latest_possible_sample () const
|
|||
/* non-audio regions have a length that may vary based on their
|
||||
* position, so we have to pass it in the call.
|
||||
*/
|
||||
minlen = min (minlen, (*i)->length (_position));
|
||||
#warning NUTEMPO FIXME source needs timeline types
|
||||
// minlen = min (minlen, (*i)->length_samples ((*i)->timeline_position()));
|
||||
}
|
||||
|
||||
/* the latest possible last sample is determined by the current
|
||||
* position, plus the shortest source extent past _start.
|
||||
*/
|
||||
|
||||
return _position + (minlen - _start) - 1;
|
||||
return position_sample() + (minlen - start_sample()) - 1;
|
||||
}
|
||||
|
||||
timepos_t
|
||||
Region::source_position () const
|
||||
{
|
||||
return _position.val().earlier (_start.val());
|
||||
}
|
||||
|
||||
timepos_t
|
||||
Region::source_relative_position (timepos_t const & p) const
|
||||
{
|
||||
return p.earlier (source_position());
|
||||
}
|
||||
|
||||
timepos_t
|
||||
Region::region_relative_position (timepos_t const & p) const
|
||||
{
|
||||
return p.earlier (_position.val());
|
||||
}
|
||||
|
||||
|
|
|
@ -52,8 +52,10 @@ Reverse::run (boost::shared_ptr<Region> r, Progress*)
|
|||
int ret = -1;
|
||||
|
||||
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(r);
|
||||
if (!region)
|
||||
|
||||
if (!region) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* create new sources */
|
||||
|
||||
|
@ -61,13 +63,13 @@ Reverse::run (boost::shared_ptr<Region> r, Progress*)
|
|||
goto out;
|
||||
}
|
||||
|
||||
fstart = region->start();
|
||||
fstart = region->start_sample();
|
||||
|
||||
if (blocksize > region->length()) {
|
||||
blocksize = region->length();
|
||||
if (blocksize > region->length_samples()) {
|
||||
blocksize = region->length_samples();
|
||||
}
|
||||
|
||||
fpos = max (fstart, (fstart + region->length() - blocksize));
|
||||
fpos = max (fstart, (fstart + region->length_samples() - blocksize));
|
||||
|
||||
buf = new Sample[blocksize];
|
||||
to_read = blocksize;
|
||||
|
|
|
@ -66,7 +66,7 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
|
||||
const AudioIntervalResult& silence = sm->second;
|
||||
|
||||
if (silence.size () == 1 && silence.front().first == 0 && silence.front().second == region->length() - 1) {
|
||||
if (silence.size () == 1 && silence.front().first == 0 && silence.front().second == region->length_samples() - 1) {
|
||||
/* the region is all silence, so just return with nothing */
|
||||
return 0;
|
||||
}
|
||||
|
@ -82,8 +82,8 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
|
||||
/* Add the possible audible section at the start of the region */
|
||||
AudioIntervalResult::const_iterator first_silence = silence.begin ();
|
||||
if (first_silence->first != region->start()) {
|
||||
audible.push_back (std::make_pair (r->start(), first_silence->first));
|
||||
if (first_silence->first != region->start_sample()) {
|
||||
audible.push_back (std::make_pair (r->start_sample(), first_silence->first));
|
||||
}
|
||||
|
||||
/* Add audible sections in the middle of the region */
|
||||
|
@ -100,7 +100,7 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
AudioIntervalResult::const_iterator last_silence = silence.end ();
|
||||
--last_silence;
|
||||
|
||||
sampleoffset_t const end_of_region = r->start() + r->length();
|
||||
sampleoffset_t const end_of_region = r->start_sample() + r->length_samples();
|
||||
|
||||
if (last_silence->second < end_of_region - 1) {
|
||||
audible.push_back (std::make_pair (last_silence->second, end_of_region - 1));
|
||||
|
@ -115,11 +115,12 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
|
|||
boost::shared_ptr<AudioRegion> copy;
|
||||
|
||||
plist.add (Properties::length, i->second - i->first);
|
||||
plist.add (Properties::position, r->position() + (i->first - r->start()));
|
||||
plist.add (Properties::position, r->position_sample() + (i->first - r->start_sample()));
|
||||
|
||||
copy = boost::dynamic_pointer_cast<AudioRegion> (
|
||||
RegionFactory::create (region, MusicSample (i->first - r->start(), 0), plist)
|
||||
);
|
||||
#warning NUTEMPO FIXME need new constructors etc.
|
||||
// copy = boost::dynamic_pointer_cast<AudioRegion> (
|
||||
// RegionFactory::create (region, MusicSample (i->first - r->start(), 0), plist)
|
||||
// );
|
||||
|
||||
copy->set_name (RegionFactory::new_region_name (region->name ()));
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user