#include <glibmm/threads.h>
#include "pbd/xml++.h"
+#include "pbd/types_convert.h"
#include "ardour/debug.h"
#include "ardour/filter.h"
#include "ardour/source.h"
#include "ardour/tempo.h"
#include "ardour/transient_detector.h"
+#include "ardour/types_convert.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace std;
using namespace ARDOUR;
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> sync_position;
+ PBD::PropertyDescriptor<samplepos_t> start;
+ PBD::PropertyDescriptor<samplecnt_t> length;
+ PBD::PropertyDescriptor<samplepos_t> position;
+ PBD::PropertyDescriptor<double> beat;
+ PBD::PropertyDescriptor<samplecnt_t> sync_position;
PBD::PropertyDescriptor<layer_t> layer;
- PBD::PropertyDescriptor<framepos_t> ancestral_start;
- PBD::PropertyDescriptor<framecnt_t> ancestral_length;
+ PBD::PropertyDescriptor<samplepos_t> ancestral_start;
+ PBD::PropertyDescriptor<samplecnt_t> ancestral_length;
PBD::PropertyDescriptor<float> stretch;
PBD::PropertyDescriptor<float> shift;
PBD::PropertyDescriptor<PositionLockStyle> position_lock_style;
Region::make_property_quarks ()
{
Properties::muted.property_id = g_quark_from_static_string (X_("muted"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for muted = %1\n", Properties::muted.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for muted = %1\n", Properties::muted.property_id));
Properties::opaque.property_id = g_quark_from_static_string (X_("opaque"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for opaque = %1\n", Properties::opaque.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for opaque = %1\n", Properties::opaque.property_id));
Properties::locked.property_id = g_quark_from_static_string (X_("locked"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for locked = %1\n", Properties::locked.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for locked = %1\n", Properties::locked.property_id));
Properties::video_locked.property_id = g_quark_from_static_string (X_("video-locked"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for video-locked = %1\n", Properties::video_locked.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for video-locked = %1\n", Properties::video_locked.property_id));
Properties::automatic.property_id = g_quark_from_static_string (X_("automatic"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for automatic = %1\n", Properties::automatic.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for automatic = %1\n", Properties::automatic.property_id));
Properties::whole_file.property_id = g_quark_from_static_string (X_("whole-file"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for whole-file = %1\n", Properties::whole_file.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for whole-file = %1\n", Properties::whole_file.property_id));
Properties::import.property_id = g_quark_from_static_string (X_("import"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for import = %1\n", Properties::import.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for import = %1\n", Properties::import.property_id));
Properties::external.property_id = g_quark_from_static_string (X_("external"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for external = %1\n", Properties::external.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for external = %1\n", Properties::external.property_id));
Properties::sync_marked.property_id = g_quark_from_static_string (X_("sync-marked"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for sync-marked = %1\n", Properties::sync_marked.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for sync-marked = %1\n", Properties::sync_marked.property_id));
Properties::left_of_split.property_id = g_quark_from_static_string (X_("left-of-split"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for left-of-split = %1\n", Properties::left_of_split.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for left-of-split = %1\n", Properties::left_of_split.property_id));
Properties::right_of_split.property_id = g_quark_from_static_string (X_("right-of-split"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for right-of-split = %1\n", Properties::right_of_split.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for right-of-split = %1\n", Properties::right_of_split.property_id));
Properties::hidden.property_id = g_quark_from_static_string (X_("hidden"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for hidden = %1\n", Properties::hidden.property_id));
+ 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));
+ 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));
+ 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));
+ 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 length = %1\n", Properties::length.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for length = %1\n", Properties::length.property_id));
Properties::position.property_id = g_quark_from_static_string (X_("position"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position = %1\n", Properties::position.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position = %1\n", Properties::position.property_id));
+ Properties::beat.property_id = g_quark_from_static_string (X_("beat"));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for beat = %1\n", Properties::beat.property_id));
Properties::sync_position.property_id = g_quark_from_static_string (X_("sync-position"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for sync-position = %1\n", Properties::sync_position.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for sync-position = %1\n", Properties::sync_position.property_id));
Properties::layer.property_id = g_quark_from_static_string (X_("layer"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layer = %1\n", Properties::layer.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layer = %1\n", Properties::layer.property_id));
Properties::ancestral_start.property_id = g_quark_from_static_string (X_("ancestral-start"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for ancestral-start = %1\n", Properties::ancestral_start.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for ancestral-start = %1\n", Properties::ancestral_start.property_id));
Properties::ancestral_length.property_id = g_quark_from_static_string (X_("ancestral-length"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for ancestral-length = %1\n", Properties::ancestral_length.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for ancestral-length = %1\n", Properties::ancestral_length.property_id));
Properties::stretch.property_id = g_quark_from_static_string (X_("stretch"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for stretch = %1\n", Properties::stretch.property_id));
+ 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));
+ 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));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position_lock_style = %1\n", Properties::position_lock_style.property_id));
Properties::layering_index.property_id = g_quark_from_static_string (X_("layering-index"));
- DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layering_index = %1\n", Properties::layering_index.property_id));
+ DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layering_index = %1\n", Properties::layering_index.property_id));
}
void
add_property (_start);
add_property (_length);
add_property (_position);
+ add_property (_beat);
add_property (_sync_position);
add_property (_ancestral_start);
add_property (_ancestral_length);
, _start (Properties::start, (s)) \
, _length (Properties::length, (l)) \
, _position (Properties::position, 0) \
+ , _beat (Properties::beat, 0.0) \
, _sync_position (Properties::sync_position, (s)) \
+ , _quarter_note (0.0) \
, _transient_user_start (0) \
, _transient_analysis_start (0) \
, _transient_analysis_end (0) \
, _start(Properties::start, other->_start) \
, _length(Properties::length, other->_length) \
, _position(Properties::position, other->_position) \
+ , _beat (Properties::beat, other->_beat) \
, _sync_position(Properties::sync_position, other->_sync_position) \
+ , _quarter_note (other->_quarter_note) \
, _user_transients (other->_user_transients) \
, _transient_user_start (other->_transient_user_start) \
, _transients (other->_transients) \
, _transient_analysis_start (other->_transient_analysis_start) \
, _transient_analysis_end (other->_transient_analysis_end) \
+ , _soloSelected (false) \
, _muted (Properties::muted, other->_muted) \
, _opaque (Properties::opaque, other->_opaque) \
, _locked (Properties::locked, other->_locked) \
, _layering_index (Properties::layering_index, other->_layering_index)
/* derived-from-derived constructor (no sources in constructor) */
-Region::Region (Session& s, framepos_t start, framecnt_t length, const string& name, DataType type)
+Region::Region (Session& s, samplepos_t start, samplecnt_t length, const string& name, DataType type)
: SessionObject(s, name)
, _type(type)
, REGION_DEFAULT_STATE(start,length)
/* override state that may have been incorrectly inherited from the other region
*/
- _position = 0;
+ _position = other->_position;
_locked = false;
_whole_file = false;
_hidden = false;
_position_lock_style = other->_position_lock_style;
_first_edit = other->_first_edit;
- _start = 0; // It seems strange _start is not inherited here?
+ _start = other->_start;
+ _beat = other->_beat;
+ _quarter_note = other->_quarter_note;
/* sync pos is relative to start of file. our start-in-file is now zero,
so set our sync position to whatever the the difference between
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, frameoffset_t offset)
+Region::Region (boost::shared_ptr<const Region> other, MusicSample offset)
: SessionObject(other->session(), other->name())
, _type (other->data_type())
, REGION_COPY_STATE (other)
/* override state that may have been incorrectly inherited from the other region
*/
- _position = 0;
_locked = false;
_whole_file = false;
_hidden = false;
use_sources (other->_sources);
set_master_sources (other->_master_sources);
- _start = other->_start + offset;
+ _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);
+ }
/* if the other region had a distinct sync point
set, then continue to use it as best we can.
}
void
-Region::set_length (framecnt_t len)
+Region::set_selected_for_solo(bool yn)
+{
+ if ( _soloSelected != yn) {
+
+ boost::shared_ptr<Playlist> pl (playlist());
+ if (pl){
+ if (yn) {
+ pl->AddToSoloSelectedList(this);
+ } else {
+ pl->RemoveFromSoloSelectedList(this);
+ }
+ }
+
+ _soloSelected = yn;
+ }
+
+}
+
+void
+Region::set_length (samplecnt_t len, const int32_t sub_num)
{
//cerr << "Region::set_length() len = " << len << endl;
if (locked()) {
length impossible.
*/
- if (max_framepos - len < _position) {
+ if (max_samplepos - len < _position) {
return;
}
}
- _last_length = _length;
- set_length_internal (len);
+ set_length_internal (len, sub_num);
_whole_file = false;
first_edit ();
maybe_uncopy ();
}
void
-Region::set_length_internal (framecnt_t len)
+Region::set_length_internal (samplecnt_t len, const int32_t sub_num)
{
+ _last_length = _length;
_length = len;
}
}
void
-Region::special_set_position (framepos_t pos)
+Region::special_set_position (samplepos_t pos)
{
/* this is used when creating a whole file region as
a way to store its "natural" or "captured" position.
_position_lock_style = ps;
- if (_position_lock_style == MusicTime) {
- _beat = _session.tempo_map().beat_at_frame (_position);
- }
-
send_change (Properties::position_lock_style);
}
}
{
boost::shared_ptr<Playlist> pl (playlist());
- if (!pl || _position_lock_style != MusicTime) {
+ if (!pl) {
return;
}
- const framepos_t pos = _session.tempo_map().frame_at_beat (_beat);
- set_position_internal (pos, false);
+ if (_position_lock_style == AudioTime) {
+ /* don't signal as the actual position has not chnged */
+ recompute_position_from_lock_style (0);
+ 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.
}
void
-Region::set_position (framepos_t pos)
+Region::set_position (samplepos_t pos, int32_t sub_num)
{
if (!can_move()) {
return;
}
- set_position_internal (pos, true);
-
/* do this even if the position is the same. this helps out
a GUI that has moved its representation already.
*/
- send_change (Properties::position);
+ PropertyChange p_and_l;
+
+ 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, false, sub_num);
+ }
+
+ if (position_lock_style() == MusicTime) {
+ p_and_l.add (Properties::length);
+ }
+
+ send_change (p_and_l);
}
-/** A gui may need to create a region, then place it in an initial
- * position determined by the user.
- * When this takes place within one gui operation, we have to reset
- * _last_position to prevent an implied move.
- */
void
-Region::set_initial_position (framepos_t pos)
+Region::set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num)
{
- if (!can_move()) {
- return;
- }
+ /* We emit a change of Properties::position even if the position hasn't changed
+ (see Region::set_position), so we must always set this up so that
+ e.g. Playlist::notify_region_moved doesn't use an out-of-date last_position.
+ */
+ _last_position = _position;
if (_position != pos) {
_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);
+ }
+
/* 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_framepos - _length < _position) {
+ if (max_samplepos - _length < _position) {
_last_length = _length;
- _length = max_framepos - _position;
+ _length = max_samplepos - _position;
}
-
- recompute_position_from_lock_style ();
- /* ensure that this move doesn't cause a range move */
- _last_position = _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.
*/
- send_change (Properties::position);
+ 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_internal (framepos_t pos, bool allow_bbt_recompute)
+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
*/
_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;
+ }
+ }
+}
+
+/** A gui may need to create a region, then place it in an initial
+ * position determined by the user.
+ * When this takes place within one gui operation, we have to reset
+ * _last_position to prevent an implied move.
+ */
+void
+Region::set_initial_position (samplepos_t pos)
+{
+ if (!can_move()) {
+ return;
+ }
+
if (_position != pos) {
_position = pos;
XXX is this the right thing to do?
*/
- if (max_framepos - _length < _position) {
+ if (max_samplepos - _length < _position) {
_last_length = _length;
- _length = max_framepos - _position;
+ _length = max_samplepos - _position;
}
- if (allow_bbt_recompute) {
- recompute_position_from_lock_style ();
- }
+ recompute_position_from_lock_style (0);
+ /* ensure that this move doesn't cause a range move */
+ _last_position = _position;
}
+
+
+ /* 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 ()
+Region::recompute_position_from_lock_style (const int32_t sub_num)
{
- if (_position_lock_style == MusicTime) {
- _beat = _session.tempo_map().beat_at_frame (_position);
- }
+ _beat = _session.tempo_map().exact_beat_at_sample (_position, sub_num);
+ _quarter_note = _session.tempo_map().exact_qn_at_sample (_position, sub_num);
}
void
-Region::nudge_position (frameoffset_t n)
+Region::nudge_position (sampleoffset_t n)
{
if (locked() || video_locked()) {
return;
return;
}
- framepos_t new_position = _position;
+ samplepos_t new_position = _position;
if (n > 0) {
- if (_position > max_framepos - n) {
- new_position = max_framepos;
+ if (_position > max_samplepos - n) {
+ new_position = max_samplepos;
} else {
new_position += n;
}
new_position += n;
}
}
-
- set_position_internal (new_position, true);
+ /* assumes non-musical nudge */
+ set_position_internal (new_position, true, 0);
send_change (Properties::position);
}
void
-Region::set_ancestral_data (framepos_t s, framecnt_t l, float st, float sh)
+Region::set_ancestral_data (samplepos_t s, samplecnt_t l, float st, float sh)
{
_ancestral_length = l;
_ancestral_start = s;
}
void
-Region::set_start (framepos_t pos)
+Region::set_start (samplepos_t pos)
{
if (locked() || position_locked() || video_locked()) {
return;
}
void
-Region::move_start (frameoffset_t distance)
+Region::move_start (sampleoffset_t distance, const int32_t sub_num)
{
if (locked() || position_locked() || video_locked()) {
return;
}
- framepos_t new_start;
+ samplepos_t new_start;
if (distance > 0) {
- if (_start > max_framepos - distance) {
- new_start = max_framepos; // makes no sense
+ if (_start > max_samplepos - distance) {
+ new_start = max_samplepos; // makes no sense
} else {
new_start = _start + distance;
}
return;
}
- set_start_internal (new_start);
+ set_start_internal (new_start, sub_num);
_whole_file = false;
first_edit ();
}
void
-Region::trim_front (framepos_t new_position)
+Region::trim_front (samplepos_t new_position, const int32_t sub_num)
{
- modify_front (new_position, false);
+ modify_front (new_position, false, sub_num);
}
void
-Region::cut_front (framepos_t new_position)
+Region::cut_front (samplepos_t new_position, const int32_t sub_num)
{
- modify_front (new_position, true);
+ modify_front (new_position, true, sub_num);
}
void
-Region::cut_end (framepos_t new_endpoint)
+Region::cut_end (samplepos_t new_endpoint, const int32_t sub_num)
{
- modify_end (new_endpoint, true);
+ modify_end (new_endpoint, true, sub_num);
}
void
-Region::modify_front (framepos_t new_position, bool reset_fade)
+Region::modify_front (samplepos_t new_position, bool reset_fade, const int32_t sub_num)
{
if (locked()) {
return;
}
- framepos_t end = last_frame();
- framepos_t source_zero;
+ samplepos_t end = last_sample();
+ samplepos_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 = 0;
+ samplecnt_t newlen = 0;
if (!can_trim_start_before_source_start ()) {
/* can't trim it back past where source position zero is located */
newlen = _length + (_position - new_position);
}
- trim_to_internal (new_position, newlen);
+ trim_to_internal (new_position, newlen, sub_num);
if (reset_fade) {
_right_of_split = true;
}
void
-Region::modify_end (framepos_t new_endpoint, bool reset_fade)
+Region::modify_end (samplepos_t new_endpoint, bool reset_fade, const int32_t sub_num)
{
if (locked()) {
return;
}
if (new_endpoint > _position) {
- trim_to_internal (_position, new_endpoint - _position);
+ trim_to_internal (_position, new_endpoint - _position, sub_num);
if (reset_fade) {
_left_of_split = true;
}
*/
void
-Region::trim_end (framepos_t new_endpoint)
+Region::trim_end (samplepos_t new_endpoint, const int32_t sub_num)
{
- modify_end (new_endpoint, false);
+ modify_end (new_endpoint, false, sub_num);
}
void
-Region::trim_to (framepos_t position, framecnt_t length)
+Region::trim_to (samplepos_t position, samplecnt_t length, const int32_t sub_num)
{
if (locked()) {
return;
}
- trim_to_internal (position, length);
+ trim_to_internal (position, length, sub_num);
if (!property_changes_suspended()) {
recompute_at_start ();
}
void
-Region::trim_to_internal (framepos_t position, framecnt_t length)
+Region::trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num)
{
- framepos_t new_start;
+ samplepos_t new_start;
if (locked()) {
return;
}
- frameoffset_t const start_shift = position - _position;
+ sampleoffset_t const start_shift = position - _position;
if (start_shift > 0) {
- if (_start > max_framepos - start_shift) {
- new_start = max_framepos;
+ if (_start > max_samplepos - start_shift) {
+ new_start = max_samplepos;
} else {
new_start = _start + start_shift;
}
PropertyChange what_changed;
if (_start != new_start) {
- set_start_internal (new_start);
+ set_start_internal (new_start, sub_num);
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
- * 2. we call set_position_internal; position is set and length in frames re-computed using
+ * 2. we call set_position_internal; position is set and length in samples re-computed using
* length in beats from (1) but at the new position, which is wrong if the region
* straddles a tempo/meter change.
*/
if (!property_changes_suspended()) {
_last_position = _position;
}
- set_position_internal (position, true);
+ set_position_internal (position, true, sub_num);
what_changed.add (Properties::position);
}
if (!property_changes_suspended()) {
_last_length = _length;
}
- set_length_internal (length);
+ set_length_internal (length, sub_num);
what_changed.add (Properties::length);
}
* @param absolute_pos Session time.
*/
void
-Region::set_sync_position (framepos_t absolute_pos)
+Region::set_sync_position (samplepos_t absolute_pos)
{
/* position within our file */
- framepos_t const file_pos = _start + (absolute_pos - _position);
+ samplepos_t const file_pos = _start + (absolute_pos - _position);
if (file_pos != _sync_position) {
_sync_marked = true;
}
}
-/* @return the sync point relative the first frame of the region */
-frameoffset_t
+/* @return the sync point relative the first sample of the region */
+sampleoffset_t
Region::sync_offset (int& dir) const
{
if (sync_marked()) {
}
}
-framepos_t
-Region::adjust_to_sync (framepos_t pos) const
+samplepos_t
+Region::adjust_to_sync (samplepos_t pos) const
{
int sync_dir;
- frameoffset_t offset = sync_offset (sync_dir);
+ sampleoffset_t offset = sync_offset (sync_dir);
// cerr << "adjusting pos = " << pos << " to sync at " << _sync_position << " offset = " << offset << " with dir = " << sync_dir << endl;
pos = 0;
}
} else {
- if (max_framepos - pos > offset) {
+ if (max_samplepos - pos > offset) {
pos += offset;
}
}
}
/** @return Sync position in session time */
-framepos_t
+samplepos_t
Region::sync_position() const
{
if (sync_marked()) {
Region::state ()
{
XMLNode *node = new XMLNode ("Region");
- char buf[64];
char buf2[64];
- LocaleGuard lg;
- const char* fe = NULL;
/* custom version of 'add_properties (*node);'
* skip values that have have dedicated save functions
i->second->get_value (*node);
}
- id().print (buf, sizeof (buf));
- node->add_property ("id", buf);
- node->add_property ("type", _type.to_string());
+ node->set_property ("id", id ());
+ node->set_property ("type", _type);
+
+ std::string fe;
switch (_first_edit) {
case EditChangesNothing:
break;
}
- node->add_property ("first-edit", fe);
+ node->set_property ("first-edit", fe);
/* note: flags are stored by derived classes */
- if (_position_lock_style != AudioTime) {
- snprintf (buf, sizeof(buf), "%lf", _beat);
- node->add_property ("beat", buf);
- }
-
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);
+ node->set_property (buf2, _sources[n]->id());
}
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);
+ node->set_property (buf2, _master_sources[n]->id ());
}
/* Only store nested sources for the whole-file region that acts
int
Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_changed, bool send)
{
- XMLProperty const * prop;
Timecode::BBT_Time bbt_time;
Stateful::save_extra_xml (node);
set_id (node);
if (_position_lock_style == MusicTime) {
- if ((prop = node.property ("bbt-position")) == 0) {
- if ((prop = node.property ("beat")) == 0) {
- /* missing BBT info, revert to audio time locking */
- _position_lock_style = AudioTime;
- } else {
- if (sscanf (prop->value().c_str(), "%lf", &_beat) != 1) {
- _position_lock_style = AudioTime;
- }
- }
-
- } else {
- if (sscanf (prop->value().c_str(), "%d|%d|%d",
+ std::string bbt_str;
+ if (node.get_property ("bbt-position", bbt_str)) {
+ if (sscanf (bbt_str.c_str(), "%d|%d|%d",
&bbt_time.bars,
&bbt_time.beats,
&bbt_time.ticks) != 3) {
_position_lock_style = AudioTime;
+ _beat = _session.tempo_map().beat_at_sample (_position);
} else {
_beat = _session.tempo_map().beat_at_bbt (bbt_time);
}
+ /* no position property change for legacy Property, so we do this here */
+ _quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
}
}
}
/* Quick fix for 2.x sessions when region is muted */
- if ((prop = node.property (X_("flags")))) {
- if (string::npos != prop->value().find("Muted")){
+ std::string flags;
+ if (node.get_property (X_("flags"), flags)) {
+ if (string::npos != flags.find("Muted")){
set_muted (true);
}
}
bool
Region::overlap_equivalent (boost::shared_ptr<const Region> other) const
{
- return coverage (other->first_frame(), other->last_frame()) != Evoral::OverlapNone;
+ return coverage (other->first_sample(), other->last_sample()) != Evoral::OverlapNone;
}
bool
return res.str();
}
+void
+Region::deep_sources (std::set<boost::shared_ptr<Source> > & sources) const
+{
+ for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
+
+ boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
+
+ if (ps) {
+ if (sources.find (ps) == sources.end()) {
+ /* (Playlist)Source not currently in
+ accumulating set, so recurse.
+ */
+ ps->playlist()->deep_sources (sources);
+ }
+ }
+
+ /* add this source */
+ sources.insert (*i);
+ }
+
+ for (SourceList::const_iterator i = _master_sources.begin(); i != _master_sources.end(); ++i) {
+
+ boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
+
+ if (ps) {
+ if (sources.find (ps) == sources.end()) {
+ /* (Playlist)Source not currently in
+ accumulating set, so recurse.
+ */
+ ps->playlist()->deep_sources (sources);
+ }
+ }
+
+ /* add this source */
+ sources.insert (*i);
+ }
+}
+
bool
-Region::uses_source (boost::shared_ptr<const Source> source) const
+Region::uses_source (boost::shared_ptr<const Source> source, bool shallow) const
{
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
if (*i == source) {
return true;
}
- boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
+ if (!shallow) {
+ boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
- if (ps) {
- if (ps->playlist()->uses_source (source)) {
- return true;
+ if (ps) {
+ if (ps->playlist()->uses_source (source)) {
+ return true;
+ }
}
}
}
return true;
}
- boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
+ if (!shallow) {
+ boost::shared_ptr<PlaylistSource> ps = boost::dynamic_pointer_cast<PlaylistSource> (*i);
- if (ps) {
- if (ps->playlist()->uses_source (source)) {
- return true;
+ if (ps) {
+ if (ps->playlist()->uses_source (source)) {
+ return true;
+ }
}
}
}
return false;
}
-framecnt_t
+
+samplecnt_t
Region::source_length(uint32_t n) const
{
assert (n < _sources.size());
}
bool
-Region::verify_length (framecnt_t& len)
+Region::verify_length (samplecnt_t& len)
{
if (source() && (source()->destructive() || source()->length_mutable())) {
return true;
}
- framecnt_t maxlen = 0;
+ samplecnt_t maxlen = 0;
for (uint32_t n = 0; n < _sources.size(); ++n) {
maxlen = max (maxlen, source_length(n) - _start);
}
bool
-Region::verify_start_and_length (framepos_t new_start, framecnt_t& new_length)
+Region::verify_start_and_length (samplepos_t new_start, samplecnt_t& new_length)
{
if (source() && (source()->destructive() || source()->length_mutable())) {
return true;
}
- framecnt_t maxlen = 0;
+ samplecnt_t maxlen = 0;
for (uint32_t n = 0; n < _sources.size(); ++n) {
maxlen = max (maxlen, source_length(n) - new_start);
}
bool
-Region::verify_start (framepos_t pos)
+Region::verify_start (samplepos_t pos)
{
if (source() && (source()->destructive() || source()->length_mutable())) {
return true;
}
bool
-Region::verify_start_mutable (framepos_t& new_start)
+Region::verify_start_mutable (samplepos_t& new_start)
{
if (source() && (source()->destructive() || source()->length_mutable())) {
return true;
if (cnt > 1 ) {
afl.sort ();
// remove exact duplicates
- TransientDetector::cleanup_transients (afl, _session.frame_rate(), 0);
+ TransientDetector::cleanup_transients (afl, _session.sample_rate(), 0);
}
}
}
void
-Region::merge_features (AnalysisFeatureList& result, const AnalysisFeatureList& src, const frameoffset_t off) const
+Region::merge_features (AnalysisFeatureList& result, const AnalysisFeatureList& src, const sampleoffset_t off) const
{
for (AnalysisFeatureList::const_iterator x = src.begin(); x != src.end(); ++x) {
- const frameoffset_t p = (*x) + off;
- if (p < first_frame() || p > last_frame()) {
+ const sampleoffset_t p = (*x) + off;
+ if (p < first_sample() || p > last_sample()) {
continue;
}
result.push_back (p);
void
Region::post_set (const PropertyChange& pc)
{
- if (pc.contains (Properties::position)) {
- recompute_position_from_lock_style ();
- }
+ _quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
}
void
-Region::set_start_internal (framecnt_t s)
+Region::set_start_internal (samplecnt_t s, const int32_t sub_num)
{
_start = s;
}
-framepos_t
+samplepos_t
Region::earliest_possible_position () const
{
if (_start > _position) {
}
}
-framecnt_t
-Region::latest_possible_frame () const
+samplecnt_t
+Region::latest_possible_sample () const
{
- framecnt_t minlen = max_framecnt;
+ samplecnt_t minlen = max_samplecnt;
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
/* non-audio regions have a length that may vary based on their
minlen = min (minlen, (*i)->length (_position));
}
- /* the latest possible last frame is determined by the current
+ /* the latest possible last sample is determined by the current
* position, plus the shortest source extent past _start.
*/
return _position + (minlen - _start) - 1;
}
-