summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-01-04 17:55:42 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-01-04 17:55:42 +0000
commit2858b0474e4bedf3ab67a539a7f0d12380ac7bda (patch)
treeb0f056f7fb0001c008b33275a8cfe885cfea2575
parentb9a9d8d0471c28e80e350d6e49cde965f87b986b (diff)
fix (?) tricky locking issues in the tempo map by adding a second lock and independently locking the metrics and the map itself
git-svn-id: svn://localhost/ardour2/branches/3.0@11157 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/ardour/ardour/tempo.h33
-rw-r--r--libs/ardour/tempo.cc242
2 files changed, 156 insertions, 119 deletions
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h
index 3f4b783de7..f0a63be05f 100644
--- a/libs/ardour/ardour/tempo.h
+++ b/libs/ardour/ardour/tempo.h
@@ -223,16 +223,14 @@ class TempoMap : public PBD::StatefulDestructible
typedef std::vector<BBTPoint> BBTPointList;
template<class T> void apply_with_metrics (T& obj, void (T::*method)(const Metrics&)) {
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (metrics_lock);
(obj.*method)(*metrics);
}
- const BBTPointList& map() const { return _map ; }
-
void map (BBTPointList::const_iterator&, BBTPointList::const_iterator&,
framepos_t start, framepos_t end);
- void bbt_time (framepos_t when, Timecode::BBT_Time&);
+ void bbt_time (framepos_t when, Timecode::BBT_Time&);
framecnt_t frame_time (const Timecode::BBT_Time&);
framecnt_t bbt_duration_at (framepos_t, const Timecode::BBT_Time&, int dir);
@@ -299,31 +297,32 @@ class TempoMap : public PBD::StatefulDestructible
framepos_t last_bbt_when;
bool last_bbt_valid;
Timecode::BBT_Time last_bbt;
- mutable Glib::RWLock lock;
- BBTPointList _map;
+ mutable Glib::RWLock metrics_lock;
+ mutable Glib::RWLock map_lock;
+ BBTPointList* _map;
void recompute_map (bool reassign_tempo_bbt, framepos_t end = -1);
void require_map_to (framepos_t pos);
void require_map_to (const Timecode::BBT_Time&);
- BBTPointList::const_iterator bbt_before_or_at (framepos_t);
- BBTPointList::const_iterator bbt_after_or_at (framepos_t);
- BBTPointList::const_iterator bbt_point_for (const Timecode::BBT_Time&);
-
+ BBTPointList::const_iterator bbt_before_or_at (framepos_t);
+ BBTPointList::const_iterator bbt_after_or_at (framepos_t);
+ BBTPointList::const_iterator bbt_point_for (const Timecode::BBT_Time&);
+
void timestamp_metrics_from_audio_time ();
-
+
framepos_t round_to_type (framepos_t fr, int dir, BBTPointType);
-
+
void bbt_time_unlocked (framepos_t, Timecode::BBT_Time&, const BBTPointList::const_iterator&);
-
- framecnt_t bbt_duration_at_unlocked (const Timecode::BBT_Time& when, const Timecode::BBT_Time& bbt, int dir);
-
+
+ framecnt_t bbt_duration_at_unlocked (const Timecode::BBT_Time& when, const Timecode::BBT_Time& bbt, int dir);
+
const MeterSection& first_meter() const;
const TempoSection& first_tempo() const;
-
+
int move_metric_section (MetricSection&, const Timecode::BBT_Time& to);
void do_insert (MetricSection* section);
-
+
Timecode::BBT_Time bbt_add (const Timecode::BBT_Time&, const Timecode::BBT_Time&, const TempoMetric&) const;
Timecode::BBT_Time bbt_add (const Timecode::BBT_Time& a, const Timecode::BBT_Time& b) const;
Timecode::BBT_Time bbt_subtract (const Timecode::BBT_Time&, const Timecode::BBT_Time&) const;
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 54bb23d517..e8f894c1b4 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -278,6 +278,7 @@ struct MetricSectionSorter {
TempoMap::TempoMap (framecnt_t fr)
{
metrics = new Metrics;
+ _map = new BBTPointList;
_frame_rate = fr;
last_bbt_valid = false;
BBT_Time start;
@@ -300,6 +301,8 @@ TempoMap::TempoMap (framecnt_t fr)
TempoMap::~TempoMap ()
{
+ delete metrics;
+ delete _map;
}
void
@@ -308,7 +311,7 @@ TempoMap::remove_tempo (const TempoSection& tempo, bool complete_operation)
bool removed = false;
{
- Glib::RWLock::WriterLock lm (lock);
+ Glib::RWLock::WriterLock lm (metrics_lock);
Metrics::iterator i;
for (i = metrics->begin(); i != metrics->end(); ++i) {
@@ -322,13 +325,10 @@ TempoMap::remove_tempo (const TempoSection& tempo, bool complete_operation)
}
}
}
-
- if (removed && complete_operation) {
- recompute_map (false);
- }
}
if (removed && complete_operation) {
+ recompute_map (false);
PropertyChanged (PropertyChange ());
}
}
@@ -339,7 +339,7 @@ TempoMap::remove_meter (const MeterSection& tempo, bool complete_operation)
bool removed = false;
{
- Glib::RWLock::WriterLock lm (lock);
+ Glib::RWLock::WriterLock lm (metrics_lock);
Metrics::iterator i;
for (i = metrics->begin(); i != metrics->end(); ++i) {
@@ -353,15 +353,10 @@ TempoMap::remove_meter (const MeterSection& tempo, bool complete_operation)
}
}
}
-
- if (removed && complete_operation) {
- recompute_map (true);
- }
-
-
}
if (removed && complete_operation) {
+ recompute_map (true);
PropertyChanged (PropertyChange ());
}
}
@@ -369,9 +364,6 @@ TempoMap::remove_meter (const MeterSection& tempo, bool complete_operation)
void
TempoMap::do_insert (MetricSection* section)
{
- /* CALLER MUST HOLD WRITE LOCK */
-
- bool reassign_tempo_bbt = false;
bool need_add = true;
assert (section->start().ticks == 0);
@@ -386,8 +378,6 @@ TempoMap::do_insert (MetricSection* section)
sections based on this new meter.
*/
- reassign_tempo_bbt = true;
-
if ((section->start().beats != 1) || (section->start().ticks != 0)) {
BBT_Time corrected = section->start();
@@ -469,8 +459,6 @@ TempoMap::do_insert (MetricSection* section)
metrics->insert (metrics->end(), section);
}
}
-
- recompute_map (reassign_tempo_bbt);
}
void
@@ -482,9 +470,12 @@ TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const BBT_T
remove_tempo (ts, false);
add_tempo (tempo, where);
} else {
- Glib::RWLock::WriterLock lm (lock);
- /* cannot move the first tempo section */
- *((Tempo*)&first) = tempo;
+ {
+ Glib::RWLock::WriterLock lm (metrics_lock);
+ /* cannot move the first tempo section */
+ *((Tempo*)&first) = tempo;
+ }
+
recompute_map (false);
}
@@ -495,7 +486,7 @@ void
TempoMap::add_tempo (const Tempo& tempo, BBT_Time where)
{
{
- Glib::RWLock::WriterLock lm (lock);
+ Glib::RWLock::WriterLock lm (metrics_lock);
/* new tempos always start on a beat */
where.ticks = 0;
@@ -531,10 +522,12 @@ TempoMap::add_tempo (const Tempo& tempo, BBT_Time where)
ts->update_bar_offset_from_bbt (*meter);
/* and insert it */
-
+
do_insert (ts);
}
+ recompute_map (false);
+
PropertyChanged (PropertyChange ());
}
@@ -547,9 +540,11 @@ TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const BBT_T
remove_meter (ms, false);
add_meter (meter, where);
} else {
- Glib::RWLock::WriterLock lm (lock);
- /* cannot move the first meter section */
- *((Meter*)&first) = meter;
+ {
+ Glib::RWLock::WriterLock lm (metrics_lock);
+ /* cannot move the first meter section */
+ *((Meter*)&first) = meter;
+ }
recompute_map (true);
}
@@ -560,7 +555,7 @@ void
TempoMap::add_meter (const Meter& meter, BBT_Time where)
{
{
- Glib::RWLock::WriterLock lm (lock);
+ Glib::RWLock::WriterLock lm (metrics_lock);
/* a new meter always starts a new bar on the first beat. so
round the start time appropriately. remember that
@@ -576,10 +571,12 @@ TempoMap::add_meter (const Meter& meter, BBT_Time where)
/* new meters *always* start on a beat. */
where.ticks = 0;
-
+
do_insert (new MeterSection (where, meter.divisions_per_bar(), meter.note_divisor()));
}
+ recompute_map (true);
+
#ifndef NDEBUG
if (DEBUG_ENABLED(DEBUG::TempoMap)) {
dump (std::cerr);
@@ -598,10 +595,10 @@ TempoMap::change_initial_tempo (double beats_per_minute, double note_type)
for (Metrics::iterator i = metrics->begin(); i != metrics->end(); ++i) {
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
{
- Glib::RWLock::WriterLock lm (lock);
+ Glib::RWLock::WriterLock lm (metrics_lock);
*((Tempo*) t) = newtempo;
- recompute_map (false);
}
+ recompute_map (false);
PropertyChanged (PropertyChange ());
break;
}
@@ -648,12 +645,12 @@ TempoMap::change_existing_tempo_at (framepos_t where, double beats_per_minute, d
/* reset */
{
- Glib::RWLock::WriterLock lm (lock);
+ Glib::RWLock::WriterLock lm (metrics_lock);
/* cannot move the first tempo section */
*((Tempo*)prev) = newtempo;
- recompute_map (false);
}
+ recompute_map (false);
PropertyChanged (PropertyChange ());
}
@@ -774,7 +771,14 @@ TempoMap::timestamp_metrics_from_audio_time ()
void
TempoMap::require_map_to (framepos_t pos)
{
- if (_map.empty() || _map.back().frame < pos) {
+ bool revise_map;
+
+ {
+ Glib::RWLock::ReaderLock lm (map_lock);
+ revise_map = (_map->empty() || _map->back().frame < pos);
+ }
+
+ if (revise_map) {
recompute_map (false, pos);
}
}
@@ -782,7 +786,14 @@ TempoMap::require_map_to (framepos_t pos)
void
TempoMap::require_map_to (const BBT_Time& bbt)
{
- if (_map.empty() || _map.back().bbt() < bbt) {
+ bool revise_map;
+
+ {
+ Glib::RWLock::ReaderLock lm (map_lock);
+ revise_map = (_map->empty() || _map->back().bbt() < bbt);
+ }
+
+ if (revise_map) {
recompute_map (false, 99);
}
}
@@ -799,20 +810,24 @@ TempoMap::recompute_map (bool reassign_tempo_bbt, framepos_t end)
double current_frame;
BBT_Time current;
Metrics::iterator next_metric;
+ BBTPointList* new_map = new BBTPointList;
if (end < 0) {
- if (_map.empty()) {
+
+ Glib::RWLock::ReaderLock lm (map_lock);
+
+ if (_map->empty()) {
/* compute 1 mins worth */
end = _frame_rate * 60;
} else {
- end = _map.back().frame;
+ end = _map->back().frame;
}
}
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("recomputing tempo map, zero to %1\n", end));
-
- _map.clear ();
+ Glib::RWLock::ReaderLock lm (metrics_lock);
+
for (Metrics::iterator i = metrics->begin(); i != metrics->end(); ++i) {
if ((ms = dynamic_cast<MeterSection *> (*i)) != 0) {
meter = ms;
@@ -873,7 +888,7 @@ TempoMap::recompute_map (bool reassign_tempo_bbt, framepos_t end)
++next_metric; // skip tempo (or meter)
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("Add first bar at 1|1 @ %2\n", current.bars, current_frame));
- _map.push_back (BBTPoint (*meter, *tempo,(framepos_t) llrint(current_frame), 1, 1));
+ new_map->push_back (BBTPoint (*meter, *tempo,(framepos_t) llrint(current_frame), 1, 1));
while (current_frame < end) {
@@ -973,18 +988,24 @@ TempoMap::recompute_map (bool reassign_tempo_bbt, framepos_t end)
if (current.beats == 1) {
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("Add Bar at %1|1 @ %2\n", current.bars, current_frame));
- _map.push_back (BBTPoint (*meter, *tempo,(framepos_t) llrint(current_frame), current.bars, 1));
+ new_map->push_back (BBTPoint (*meter, *tempo,(framepos_t) llrint(current_frame), current.bars, 1));
} else {
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("Add Beat at %1|%2 @ %3\n", current.bars, current.beats, current_frame));
- _map.push_back (BBTPoint (*meter, *tempo, (framepos_t) llrint(current_frame), current.bars, current.beats));
+ new_map->push_back (BBTPoint (*meter, *tempo, (framepos_t) llrint(current_frame), current.bars, current.beats));
}
}
+
+ {
+ Glib::RWLock::WriterLock lm (map_lock);
+ swap (_map, new_map);
+ delete new_map;
+ }
}
TempoMetric
TempoMap::metric_at (framepos_t frame) const
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (metrics_lock);
TempoMetric m (first_meter(), first_tempo());
const Meter* meter;
const Tempo* tempo;
@@ -1021,7 +1042,7 @@ TempoMap::metric_at (framepos_t frame) const
TempoMetric
TempoMap::metric_at (BBT_Time bbt) const
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (metrics_lock);
TempoMetric m (first_meter(), first_tempo());
const Meter* meter;
const Tempo* tempo;
@@ -1058,7 +1079,7 @@ void
TempoMap::bbt_time (framepos_t frame, BBT_Time& bbt)
{
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (map_lock);
BBTPointList::const_iterator i = bbt_before_or_at (frame);
bbt_time_unlocked (frame, bbt, i);
}
@@ -1081,7 +1102,7 @@ TempoMap::bbt_time_unlocked (framepos_t frame, BBT_Time& bbt, const BBTPointList
framepos_t
TempoMap::frame_time (const BBT_Time& bbt)
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (map_lock);
BBTPointList::const_iterator s = bbt_point_for (BBT_Time (1, 1, 0));
BBTPointList::const_iterator e = bbt_point_for (BBT_Time (bbt.bars, bbt.beats, 0));
@@ -1097,7 +1118,7 @@ TempoMap::frame_time (const BBT_Time& bbt)
framecnt_t
TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir)
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (map_lock);
framecnt_t frames = 0;
BBT_Time when;
@@ -1119,7 +1140,7 @@ TempoMap::bbt_duration_at_unlocked (const BBT_Time& when, const BBT_Time& bbt, i
BBTPointList::const_iterator start (wi);
double tick_frames = 0;
- assert (wi != _map.end());
+ assert (wi != _map->end());
/* compute how much rounding we did because of non-zero ticks */
@@ -1130,19 +1151,19 @@ TempoMap::bbt_duration_at_unlocked (const BBT_Time& when, const BBT_Time& bbt, i
uint32_t bars = 0;
uint32_t beats = 0;
- while (wi != _map.end() && bars < bbt.bars) {
+ while (wi != _map->end() && bars < bbt.bars) {
++wi;
if ((*wi).is_bar()) {
++bars;
}
}
- assert (wi != _map.end());
+ assert (wi != _map->end());
- while (wi != _map.end() && beats < bbt.beats) {
+ while (wi != _map->end() && beats < bbt.beats) {
++wi;
++beats;
}
- assert (wi != _map.end());
+ assert (wi != _map->end());
/* add any additional frames related to ticks in the added value */
@@ -1156,25 +1177,19 @@ TempoMap::bbt_duration_at_unlocked (const BBT_Time& when, const BBT_Time& bbt, i
framepos_t
TempoMap::round_to_bar (framepos_t fr, int dir)
{
- {
- Glib::RWLock::ReaderLock lm (lock);
- return round_to_type (fr, dir, Bar);
- }
+ return round_to_type (fr, dir, Bar);
}
framepos_t
TempoMap::round_to_beat (framepos_t fr, int dir)
{
- {
- Glib::RWLock::ReaderLock lm (lock);
- return round_to_type (fr, dir, Beat);
- }
+ return round_to_type (fr, dir, Beat);
}
framepos_t
TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, int dir)
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (map_lock);
BBTPointList::const_iterator i = bbt_before_or_at (fr);
BBT_Time the_beat;
uint32_t ticks_one_subdivisions_worth;
@@ -1204,9 +1219,9 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, int dir)
}
if (the_beat.ticks > BBT_Time::ticks_per_bar_division) {
- assert (i != _map.end());
+ assert (i != _map->end());
++i;
- assert (i != _map.end());
+ assert (i != _map->end());
the_beat.ticks -= BBT_Time::ticks_per_bar_division;
}
@@ -1229,7 +1244,7 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, int dir)
}
if (the_beat.ticks < difference) {
- if (i == _map.begin()) {
+ if (i == _map->begin()) {
/* can't go backwards from wherever pos is, so just return it */
return fr;
}
@@ -1255,9 +1270,9 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, int dir)
DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("moved forward to %1\n", the_beat.ticks));
if (the_beat.ticks > BBT_Time::ticks_per_bar_division) {
- assert (i != _map.end());
+ assert (i != _map->end());
++i;
- assert (i != _map.end());
+ assert (i != _map->end());
the_beat.ticks -= BBT_Time::ticks_per_bar_division;
DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("fold beat to %1\n", the_beat));
}
@@ -1267,7 +1282,7 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, int dir)
/* closer to previous subdivision, so shift backward */
if (rem > the_beat.ticks) {
- if (i == _map.begin()) {
+ if (i == _map->begin()) {
/* can't go backwards past zero, so ... */
return 0;
}
@@ -1291,6 +1306,7 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, int dir)
framepos_t
TempoMap::round_to_type (framepos_t frame, int dir, BBTPointType type)
{
+ Glib::RWLock::ReaderLock lm (map_lock);
BBTPointList::const_iterator fi;
if (dir > 0) {
@@ -1299,7 +1315,7 @@ TempoMap::round_to_type (framepos_t frame, int dir, BBTPointType type)
fi = bbt_before_or_at (frame);
}
- assert (fi != _map.end());
+ assert (fi != _map->end());
DEBUG_TRACE(DEBUG::SnapBBT, string_compose ("round from %1 (%3|%4 @ %5) to bars in direction %2\n", frame, dir, (*fi).bar, (*fi).beat, (*fi).frame));
@@ -1313,7 +1329,7 @@ TempoMap::round_to_type (framepos_t frame, int dir, BBTPointType type)
}
while (!(*fi).is_bar()) {
- if (fi == _map.begin()) {
+ if (fi == _map->begin()) {
break;
}
fi--;
@@ -1332,7 +1348,7 @@ TempoMap::round_to_type (framepos_t frame, int dir, BBTPointType type)
while (!(*fi).is_bar()) {
fi++;
- if (fi == _map.end()) {
+ if (fi == _map->end()) {
--fi;
break;
}
@@ -1354,7 +1370,7 @@ TempoMap::round_to_type (framepos_t frame, int dir, BBTPointType type)
}
while ((*prev).beat != 1) {
- if (prev == _map.begin()) {
+ if (prev == _map->begin()) {
break;
}
prev--;
@@ -1362,7 +1378,7 @@ TempoMap::round_to_type (framepos_t frame, int dir, BBTPointType type)
while ((*next).beat != 1) {
next++;
- if (next == _map.end()) {
+ if (next == _map->end()) {
--next;
break;
}
@@ -1425,18 +1441,15 @@ TempoMap::map (TempoMap::BBTPointList::const_iterator& begin,
TempoMap::BBTPointList::const_iterator& end,
framepos_t lower, framepos_t upper)
{
- if (_map.empty() || upper >= _map.back().frame) {
- recompute_map (false, upper);
- }
-
- begin = lower_bound (_map.begin(), _map.end(), lower);
- end = upper_bound (_map.begin(), _map.end(), upper);
+ require_map_to (upper);
+ begin = lower_bound (_map->begin(), _map->end(), lower);
+ end = upper_bound (_map->begin(), _map->end(), upper);
}
const TempoSection&
TempoMap::tempo_section_at (framepos_t frame) const
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (metrics_lock);
Metrics::const_iterator i;
TempoSection* prev = 0;
@@ -1482,7 +1495,7 @@ TempoMap::get_state ()
XMLNode *root = new XMLNode ("TempoMap");
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (metrics_lock);
for (i = metrics->begin(); i != metrics->end(); ++i) {
root->add_child_nocopy ((*i)->get_state());
}
@@ -1495,7 +1508,7 @@ int
TempoMap::set_state (const XMLNode& node, int /*version*/)
{
{
- Glib::RWLock::WriterLock lm (lock);
+ Glib::RWLock::WriterLock lm (metrics_lock);
XMLNodeList nlist;
XMLNodeConstIterator niter;
@@ -1545,13 +1558,12 @@ TempoMap::set_state (const XMLNode& node, int /*version*/)
}
if (niter == nlist.end()) {
-
MetricSectionSorter cmp;
metrics->sort (cmp);
- recompute_map (true);
}
}
+ recompute_map (true);
PropertyChanged (PropertyChange ());
return 0;
@@ -1560,6 +1572,7 @@ TempoMap::set_state (const XMLNode& node, int /*version*/)
void
TempoMap::dump (std::ostream& o) const
{
+ Glib::RWLock::ReaderLock lm (metrics_lock);
const MeterSection* m;
const TempoSection* t;
@@ -1578,7 +1591,7 @@ TempoMap::dump (std::ostream& o) const
int
TempoMap::n_tempos() const
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (metrics_lock);
int cnt = 0;
for (Metrics::const_iterator i = metrics->begin(); i != metrics->end(); ++i) {
@@ -1593,7 +1606,7 @@ TempoMap::n_tempos() const
int
TempoMap::n_meters() const
{
- Glib::RWLock::ReaderLock lm (lock);
+ Glib::RWLock::ReaderLock lm (metrics_lock);
int cnt = 0;
for (Metrics::const_iterator i = metrics->begin(); i != metrics->end(); ++i) {
@@ -1608,6 +1621,7 @@ TempoMap::n_meters() const
void
TempoMap::insert_time (framepos_t where, framecnt_t amount)
{
+ Glib::RWLock::WriterLock lm (metrics_lock);
for (Metrics::iterator i = metrics->begin(); i != metrics->end(); ++i) {
if ((*i)->frame() >= where && (*i)->movable ()) {
(*i)->set_frame ((*i)->frame() + amount);
@@ -1638,6 +1652,7 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats)
framepos_t
TempoMap::framepos_minus_bbt (framepos_t pos, BBT_Time op)
{
+ Glib::RWLock::ReaderLock lm (map_lock);
BBTPointList::const_iterator i;
framecnt_t extra_frames = 0;
@@ -1650,7 +1665,7 @@ TempoMap::framepos_minus_bbt (framepos_t pos, BBT_Time op)
/* walk backwards */
- while (i != _map.begin() && (op.bars || op.beats)) {
+ while (i != _map->begin() && (op.bars || op.beats)) {
--i;
if ((*i).is_bar()) {
if (op.bars) {
@@ -1683,6 +1698,7 @@ TempoMap::framepos_minus_bbt (framepos_t pos, BBT_Time op)
framepos_t
TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op)
{
+ Glib::RWLock::ReaderLock lm (map_lock);
BBT_Time op_copy (op);
int additional_minutes = 1;
BBTPointList::const_iterator i;
@@ -1697,7 +1713,7 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op)
/* we know that (*i).frame is before or equal to pos */
backup_frames = pos - (*i).frame;
- while (i != _map.end() && (op.bars || op.beats)) {
+ while (i != _map->end() && (op.bars || op.beats)) {
++i;
if ((*i).is_bar()) {
if (op.bars) {
@@ -1710,7 +1726,7 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op)
}
}
- if (i != _map.end()) {
+ if (i != _map->end()) {
break;
}
@@ -1722,7 +1738,7 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op)
/* go back and try again */
warning << "reached end of map with op now at " << op << " end = "
- << _map.back().frame << ' ' << _map.back().bar << '|' << _map.back().beat << ", trying to walk "
+ << _map->back().frame << ' ' << _map->back().bar << '|' << _map->back().beat << ", trying to walk "
<< op_copy << " ... retry"
<< endmsg;
}
@@ -1741,6 +1757,7 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op)
Evoral::MusicalTime
TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance)
{
+ Glib::RWLock::ReaderLock lm (map_lock);
BBTPointList::const_iterator i = bbt_after_or_at (pos);
Evoral::MusicalTime beats = 0;
framepos_t end = pos + distance;
@@ -1755,11 +1772,11 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance)
beats += ((*i).frame - pos) / (*i).meter->frames_per_division (*(*i).tempo, _frame_rate);
}
- while (i != _map.end() && (*i).frame < end) {
+ while (i != _map->end() && (*i).frame < end) {
++i;
beats++;
}
- assert (i != _map.end());
+ assert (i != _map->end());
/* if our ending BBTPoint is after the end, subtract a fractional beat
to represent that distance.
@@ -1775,12 +1792,17 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance)
TempoMap::BBTPointList::const_iterator
TempoMap::bbt_before_or_at (framepos_t pos)
{
+ BBTPointList::const_iterator i;
+
require_map_to (pos);
- BBTPointList::const_iterator i = lower_bound (_map.begin(), _map.end(), pos);
- assert (i != _map.end());
- if ((*i).frame > pos) {
- assert (i != _map.begin());
- --i;
+ {
+ Glib::RWLock::ReaderLock lm (map_lock);
+ i = lower_bound (_map->begin(), _map->end(), pos);
+ assert (i != _map->end());
+ if ((*i).frame > pos) {
+ assert (i != _map->begin());
+ --i;
+ }
}
return i;
}
@@ -1788,9 +1810,14 @@ TempoMap::bbt_before_or_at (framepos_t pos)
TempoMap::BBTPointList::const_iterator
TempoMap::bbt_after_or_at (framepos_t pos)
{
+ BBTPointList::const_iterator i;
+
require_map_to (pos);
- BBTPointList::const_iterator i = upper_bound (_map.begin(), _map.end(), pos);
- assert (i != _map.end());
+ {
+ Glib::RWLock::ReaderLock lm (map_lock);
+ i = upper_bound (_map->begin(), _map->end(), pos);
+ assert (i != _map->end());
+ }
return i;
}
@@ -1803,17 +1830,28 @@ struct bbtcmp {
TempoMap::BBTPointList::const_iterator
TempoMap::bbt_point_for (const BBT_Time& bbt)
{
+ BBTPointList::const_iterator i;
bbtcmp cmp;
int additional_minutes = 1;
- while (_map.empty() || _map.back().bar < (bbt.bars + 1)) {
+ while (1) {
+ {
+ Glib::RWLock::ReaderLock lm (map_lock);
+ if (!_map->empty() && _map->back().bar >= (bbt.bars + 1)) {
+ break;
+ }
+ }
/* add some more distance, using bigger steps each time */
- require_map_to (_map.back().frame + (_frame_rate * 60 * additional_minutes));
+ require_map_to (_map->back().frame + (_frame_rate * 60 * additional_minutes));
additional_minutes *= 2;
}
- BBTPointList::const_iterator i = lower_bound (_map.begin(), _map.end(), bbt, cmp);
- assert (i != _map.end());
+ {
+ Glib::RWLock::ReaderLock lm (map_lock);
+ i = lower_bound (_map->begin(), _map->end(), bbt, cmp);
+ assert (i != _map->end());
+ }
+
return i;
}