enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / ardour / tempo.cc
index 417c82ea267e42ec73d6b327f2b1591b40c067ad..0c328c0b1edbc5ac254b7b00541e9707de89eae2 100644 (file)
@@ -33,7 +33,7 @@
 #include "ardour/lmath.h"
 #include "ardour/tempo.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 #include <locale.h>
 
 using namespace std;
@@ -772,13 +772,13 @@ TempoMap::remove_meter (const MeterSection& tempo, bool complete_operation)
 bool
 TempoMap::remove_meter_locked (const MeterSection& meter)
 {
-       Metrics::iterator i;
 
-       for (i = _metrics.begin(); i != _metrics.end(); ++i) {
-               TempoSection* t = 0;
-               if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
-                       if (meter.frame() == (*i)->frame()) {
-                               if (t->locked_to_meter()) {
+       if (meter.position_lock_style() == AudioTime) {
+               /* remove meter-locked tempo */
+               for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
+                       TempoSection* t = 0;
+                       if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+                               if (t->locked_to_meter() && meter.frame() == (*i)->frame()) {
                                        delete (*i);
                                        _metrics.erase (i);
                                        break;
@@ -787,7 +787,7 @@ TempoMap::remove_meter_locked (const MeterSection& meter)
                }
        }
 
-       for (i = _metrics.begin(); i != _metrics.end(); ++i) {
+       for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
                if (dynamic_cast<MeterSection*> (*i) != 0) {
                        if (meter.frame() == (*i)->frame()) {
                                if ((*i)->movable()) {
@@ -981,6 +981,7 @@ TempoMap::add_tempo_locked (const Tempo& tempo, double pulse, framepos_t frame
        TempoSection* t = new TempoSection (pulse, frame, tempo.beats_per_minute(), tempo.note_type(), type, pls);
        t->set_locked_to_meter (locked_to_meter);
        bool solved = false;
+
        do_insert (t);
 
        if (recompute) {
@@ -993,8 +994,8 @@ TempoMap::add_tempo_locked (const Tempo& tempo, double pulse, framepos_t frame
        }
 
        if (!solved && recompute) {
-               remove_tempo_locked (*t);
-               return 0;
+               warning << "Adding tempo may have left the tempo map unsolved." << endmsg;
+               recompute_map (_metrics);
        }
 
        return t;
@@ -1087,8 +1088,11 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, const BBT_Time& whe
        }
 
        if (!solved && recompute) {
-               remove_meter_locked (*new_meter);
-               return 0;
+               /* if this has failed to solve, there is little we can do other than to ensure that
+                  the new map is recalculated.
+               */
+               warning << "Adding meter may have left the tempo map unsolved." << endmsg;
+               recompute_map (_metrics);
        }
 
        return new_meter;
@@ -1246,7 +1250,7 @@ TempoMap::first_tempo ()
        return *t;
 }
 void
-TempoMap::recompute_tempos (Metrics& metrics)
+TempoMap::recompute_tempi (Metrics& metrics)
 {
        TempoSection* prev_t = 0;
 
@@ -1386,7 +1390,7 @@ TempoMap::recompute_map (Metrics& metrics, framepos_t end)
                return;
        }
 
-       recompute_tempos (metrics);
+       recompute_tempi (metrics);
        recompute_meters (metrics);
 }
 
@@ -2111,10 +2115,17 @@ TempoMap::check_solved (const Metrics& metrics) const
                        m = static_cast<MeterSection*> (*i);
                        if (prev_m && m->position_lock_style() == AudioTime) {
                                const TempoSection* t = &tempo_section_at_frame_locked (metrics, m->frame() - 1);
-                               const double nascent_m_pulse = ((m->beat() - prev_m->beat()) / prev_m->note_divisor()) + prev_m->pulse();
-                               const framepos_t nascent_m_frame = t->frame_at_pulse (nascent_m_pulse, _frame_rate);
-
-                               if (t && (nascent_m_frame > m->frame() || nascent_m_frame < 0)) {
+                               const framepos_t nascent_m_frame = t->frame_at_pulse (m->pulse(), _frame_rate);
+                               /* Here we check that a preceding section of music doesn't overlap a subsequent one.
+                                  It is complicated by the fact that audio locked meters represent a discontinuity in the pulse
+                                  (they place an exact pulse at a particular time expressed only in frames).
+                                  This has the effect of shifting the calculated frame at the meter pulse (wrt the previous section of music)
+                                  away from its actual frame (which is now the frame location of the exact pulse).
+                                  This can result in the calculated frame (from the previous musical section)
+                                  differing from the exact frame by one sample.
+                                  Allow for that.
+                               */
+                               if (t && (nascent_m_frame > m->frame() + 1 || nascent_m_frame < 0)) {
                                        return false;
                                }
                        }
@@ -2214,7 +2225,7 @@ TempoMap::solve_map_frame (Metrics& imaginary, TempoSection* section, const fram
        }
 
 #if (0)
-       recompute_tempos (imaginary);
+       recompute_tempi (imaginary);
 
        if (check_solved (imaginary)) {
                return true;
@@ -2226,7 +2237,7 @@ TempoMap::solve_map_frame (Metrics& imaginary, TempoSection* section, const fram
        MetricSectionFrameSorter fcmp;
        imaginary.sort (fcmp);
 
-       recompute_tempos (imaginary);
+       recompute_tempi (imaginary);
 
        if (check_solved (imaginary)) {
                return true;
@@ -2280,7 +2291,7 @@ TempoMap::solve_map_pulse (Metrics& imaginary, TempoSection* section, const doub
        }
 
 #if (0)
-       recompute_tempos (imaginary);
+       recompute_tempi (imaginary);
 
        if (check_solved (imaginary)) {
                return true;
@@ -2292,7 +2303,7 @@ TempoMap::solve_map_pulse (Metrics& imaginary, TempoSection* section, const doub
        MetricSectionSorter cmp;
        imaginary.sort (cmp);
 
-       recompute_tempos (imaginary);
+       recompute_tempi (imaginary);
        /* Reordering
         * XX need a restriction here, but only for this case,
         * as audio locked tempos don't interact in the same way.
@@ -2762,7 +2773,7 @@ TempoMap::gui_move_meter (MeterSection* ms, const framepos_t& frame)
 
                        if (solve_map_frame (future_map, copy, frame)) {
                                solve_map_frame (_metrics, ms, frame);
-                               recompute_tempos (_metrics);
+                               recompute_tempi (_metrics);
                        }
                }
        } else {
@@ -2775,7 +2786,7 @@ TempoMap::gui_move_meter (MeterSection* ms, const framepos_t& frame)
 
                        if (solve_map_bbt (future_map, copy, bbt)) {
                                solve_map_bbt (_metrics, ms, bbt);
-                               recompute_tempos (_metrics);
+                               recompute_tempi (_metrics);
                        }
                }
        }
@@ -2798,7 +2809,7 @@ TempoMap::gui_change_tempo (TempoSection* ts, const Tempo& bpm)
                Glib::Threads::RWLock::WriterLock lm (lock);
                TempoSection* tempo_copy = copy_metrics_and_point (_metrics, future_map, ts);
                tempo_copy->set_beats_per_minute (bpm.beats_per_minute());
-               recompute_tempos (future_map);
+               recompute_tempi (future_map);
 
                if (check_solved (future_map)) {
                        ts->set_beats_per_minute (bpm.beats_per_minute());
@@ -2947,12 +2958,12 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
                }
                new_bpm = min (new_bpm, (double) 1000.0);
                prev_t->set_beats_per_minute (new_bpm);
-               recompute_tempos (future_map);
+               recompute_tempi (future_map);
                recompute_meters (future_map);
 
                if (check_solved (future_map)) {
                        ts->set_beats_per_minute (new_bpm);
-                       recompute_tempos (_metrics);
+                       recompute_tempi (_metrics);
                        recompute_meters (_metrics);
                }
        }
@@ -2967,7 +2978,7 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
 }
 
 double
-TempoMap::exact_beat_at_frame (const framepos_t& frame, const int32_t& sub_num)
+TempoMap::exact_beat_at_frame (const framepos_t& frame, const int32_t sub_num)
 {
        Glib::Threads::RWLock::ReaderLock lm (lock);
 
@@ -2975,7 +2986,7 @@ TempoMap::exact_beat_at_frame (const framepos_t& frame, const int32_t& sub_num)
 }
 
 double
-TempoMap::exact_beat_at_frame_locked (const Metrics& metrics, const framepos_t& frame, const int32_t& sub_num)
+TempoMap::exact_beat_at_frame_locked (const Metrics& metrics, const framepos_t& frame, const int32_t sub_num)
 {
        double beat = beat_at_frame_locked (metrics, frame);
        if (sub_num > 1) {