Tempo ramps - api rename, fix various meter and tempo dialog bugs.
authornick_m <mainsbridge@gmail.com>
Fri, 5 Feb 2016 19:07:27 +0000 (06:07 +1100)
committernick_m <mainsbridge@gmail.com>
Fri, 27 May 2016 13:38:10 +0000 (23:38 +1000)
gtk2_ardour/editor_drag.cc
gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/tempo_dialog.cc
gtk2_ardour/tempo_dialog.h
libs/ardour/ardour/tempo.h
libs/ardour/lv2_plugin.cc
libs/ardour/session.cc
libs/ardour/tempo.cc

index dfd6407a6e4eca89b3b20746f12c0e175937a32b..4bde8e908c35aeae89eeb11972103cfa6b14b1d0 100644 (file)
@@ -3368,7 +3368,7 @@ TempoMarkerDrag::aborted (bool moved)
        if (moved) {
                TempoMap& map (_editor->session()->tempo_map());
                /* we removed it before, so add it back now */
-               map.add_tempo (_marker->tempo(), _marker->tempo().start(), _marker->tempo().type());
+               map.add_tempo (_marker->tempo(), _marker->tempo().beat(), _marker->tempo().type());
                // delete the dummy marker we used for visual representation while moving.
                // a new visual marker will show up automatically.
                delete _marker;
index 0cb53ee5b468e62145a22e28a261a337f060c239..836131549524943a6962beacc6edb0a77d1ad226 100644 (file)
@@ -317,7 +317,7 @@ Editor::remove_tempo_marker (ArdourCanvas::Item* item)
 void
 Editor::edit_meter_section (MeterSection* section)
 {
-       MeterDialog meter_dialog (*section, _("done"));
+       MeterDialog meter_dialog (_session->tempo_map(), *section, _("done"));
 
        switch (meter_dialog.run()) {
        case RESPONSE_ACCEPT:
@@ -336,7 +336,7 @@ Editor::edit_meter_section (MeterSection* section)
 
        begin_reversible_command (_("replace tempo mark"));
         XMLNode &before = _session->tempo_map().get_state();
-       _session->tempo_map().replace_meter (*section, Meter (bpb, note_type), _session->tempo_map().bbt_to_beats (when), when);
+       _session->tempo_map().replace_meter (*section, Meter (bpb, note_type), when);
         XMLNode &after = _session->tempo_map().get_state();
        _session->add_command(new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
        commit_reversible_command ();
@@ -345,7 +345,7 @@ Editor::edit_meter_section (MeterSection* section)
 void
 Editor::edit_tempo_section (TempoSection* section)
 {
-       TempoDialog tempo_dialog (*section, _("done"));
+       TempoDialog tempo_dialog (_session->tempo_map(), *section, _("done"));
 
        switch (tempo_dialog.run ()) {
        case RESPONSE_ACCEPT:
index 2c45d500857b91b874bbc739896c27e1ed6ce3fe..881da33617a51a6cc63dbe4c05f06f158feba31b 100644 (file)
@@ -47,10 +47,10 @@ TempoDialog::TempoDialog (TempoMap& map, framepos_t frame, const string&)
        Tempo tempo (map.tempo_at (frame));
        map.bbt_time (frame, when);
 
-       init (when, tempo.beats_per_minute(), tempo.note_type(), true);
+       init (when, tempo.beats_per_minute(), tempo.note_type(), TempoSection::Type::Constant, true);
 }
 
-TempoDialog::TempoDialog (TempoSection& section, const string&)
+TempoDialog::TempoDialog (TempoMap& map, TempoSection& section, const string&)
        : ArdourDialog (_("Edit Tempo"))
        , bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0)
        , bpm_spinner (bpm_adjustment)
@@ -59,11 +59,13 @@ TempoDialog::TempoDialog (TempoSection& section, const string&)
        , pulse_selector_label (_("Pulse note"), ALIGN_LEFT, ALIGN_CENTER)
        , tap_tempo_button (_("Tap tempo"))
 {
-       init (section.start(), section.beats_per_minute(), section.note_type(), section.movable());
+       Timecode::BBT_Time when;
+       map.bbt_time (map.frame_at_beat (section.beat()), when);
+       init (when, section.beats_per_minute(), section.note_type(), section.type(), section.movable());
 }
 
 void
-TempoDialog::init (const Timecode::BBT_Time& when, double bpm, double note_type, bool movable)
+TempoDialog::init (const Timecode::BBT_Time& when, double bpm, double note_type, TempoSection::Type type, bool movable)
 {
        vector<string> strings;
        NoteTypes::iterator x;
@@ -113,7 +115,16 @@ TempoDialog::init (const Timecode::BBT_Time& when, double bpm, double note_type,
        tempo_types.insert (make_pair (_("constant"), TempoSection::Type::Constant));
        strings.push_back (_("constant"));
        set_popdown_strings (tempo_type, strings);
-       tempo_type.set_active_text (strings[0]); // "ramped"
+       TempoTypes::iterator tt;
+       for (tt = tempo_types.begin(); tt != tempo_types.end(); ++tt) {
+               if (tt->second == type) {
+                       tempo_type.set_active_text (tt->first);
+                       break;
+               }
+       }
+       if (tt == tempo_types.end()) {
+               tempo_type.set_active_text (strings[0]); // "ramped"
+       }
 
        Table* table;
 
@@ -278,7 +289,7 @@ TempoDialog::get_tempo_type ()
        TempoTypes::iterator x = tempo_types.find (tempo_type.get_active_text());
 
        if (x == tempo_types.end()) {
-               error << string_compose(_("incomprehensible pulse note type (%1)"), tempo_type.get_active_text()) << endmsg;
+               error << string_compose(_("incomprehensible tempo type (%1)"), tempo_type.get_active_text()) << endmsg;
                return TempoSection::Type::Constant;
        }
 
@@ -354,10 +365,12 @@ MeterDialog::MeterDialog (TempoMap& map, framepos_t frame, const string&)
        init (when, meter.divisions_per_bar(), meter.note_divisor(), true);
 }
 
-MeterDialog::MeterDialog (MeterSection& section, const string&)
+MeterDialog::MeterDialog (TempoMap& map, MeterSection& section, const string&)
        : ArdourDialog (_("Edit Meter"))
 {
-       init (section.start(), section.divisions_per_bar(), section.note_divisor(), section.movable());
+       Timecode::BBT_Time when;
+       map.bbt_time (map.frame_at_beat (section.beat()), when);
+       init (when, section.divisions_per_bar(), section.note_divisor(), section.movable());
 }
 
 void
index 89f93016a2500e38c5b2eb08cceebeb9e1ecdcff..c6828e3ad255517270f586ee09f09d6c475e0103 100644 (file)
@@ -39,7 +39,7 @@ class TempoDialog : public ArdourDialog
 {
 public:
        TempoDialog (ARDOUR::TempoMap&, framepos_t, const std::string & action);
-       TempoDialog (ARDOUR::TempoSection&, const std::string & action);
+       TempoDialog (ARDOUR::TempoMap&, ARDOUR::TempoSection&, const std::string & action);
 
        double get_bpm ();
        double get_note_type ();
@@ -47,7 +47,7 @@ public:
        ARDOUR::TempoSection::Type get_tempo_type ();
 
 private:
-       void init (const Timecode::BBT_Time& start, double, double, bool);
+       void init (const Timecode::BBT_Time& start, double bpm , double note_type, ARDOUR::TempoSection::Type type, bool movable);
        bool is_user_input_valid() const;
        void bpm_changed ();
        bool bpm_button_press (GdkEventButton* );
@@ -88,7 +88,7 @@ class MeterDialog : public ArdourDialog
 public:
 
        MeterDialog (ARDOUR::TempoMap&, framepos_t, const std::string & action);
-       MeterDialog (ARDOUR::MeterSection&, const std::string & action);
+       MeterDialog (ARDOUR::TempoMap&, ARDOUR::MeterSection&, const std::string & action);
 
        double get_bpb ();
        double get_note_type ();
index a7d0d6ba995e307dc65f6f38c4ba81281069bd92..8712578e54f5bc25503396faaab334c055504916 100644 (file)
@@ -99,14 +99,13 @@ class LIBARDOUR_API Meter {
 /** A section of timeline with a certain Tempo or Meter. */
 class LIBARDOUR_API MetricSection {
   public:
-       MetricSection (double start)
-               : _beat (start), _frame (0), _movable (true), _position_lock_style (MusicTime) {}
+       MetricSection (double beat)
+               : _beat (beat), _frame (0), _movable (true), _position_lock_style (MusicTime) {}
        MetricSection (framepos_t frame)
                : _beat (0), _frame (frame), _movable (true), _position_lock_style (MusicTime) {}
 
        virtual ~MetricSection() {}
 
-       const double start () const { return _beat; }
        const double& beat () const { return _beat; }
        void set_beat (double beat) { _beat = beat;}
 
@@ -137,8 +136,8 @@ private:
 /** A section of timeline with a certain Meter. */
 class LIBARDOUR_API MeterSection : public MetricSection, public Meter {
   public:
-       MeterSection (double start, const Timecode::BBT_Time& bbt, double bpb, double note_type)
-               : MetricSection (start), Meter (bpb, note_type), _bbt (bbt) {}
+       MeterSection (double beat, const Timecode::BBT_Time& bbt, double bpb, double note_type)
+               : MetricSection (beat), Meter (bpb, note_type), _bbt (bbt) {}
        MeterSection (framepos_t frame, double bpb, double note_type)
                : MetricSection (frame), Meter (bpb, note_type) {}
        MeterSection (const XMLNode&);
@@ -147,10 +146,11 @@ class LIBARDOUR_API MeterSection : public MetricSection, public Meter {
 
        XMLNode& get_state() const;
 
-       void set_start (std::pair<double, Timecode::BBT_Time>& w) {
-               set_beat (w.first);
+       void set_beat (std::pair<double, Timecode::BBT_Time>& w) {
+               MetricSection::set_beat (w.first);
                _bbt = w.second;
        }
+
        const Timecode::BBT_Time& bbt() const { return _bbt; }
 private:
        Timecode::BBT_Time _bbt;
@@ -164,8 +164,8 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
                Constant,
        };
 
-       TempoSection (const double& start, double qpm, double note_type, Type tempo_type)
-               : MetricSection (start), Tempo (qpm, note_type), _bar_offset (-1.0), _type (tempo_type)  {}
+       TempoSection (const double& beat, double qpm, double note_type, Type tempo_type)
+               : MetricSection (beat), Tempo (qpm, note_type), _bar_offset (-1.0), _type (tempo_type)  {}
        TempoSection (framepos_t frame, double qpm, double note_type, Type tempo_type)
                : MetricSection (frame), Tempo (qpm, note_type), _bar_offset (-1.0), _type (tempo_type) {}
        TempoSection (const XMLNode&);
@@ -174,10 +174,6 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
 
        XMLNode& get_state() const;
 
-       void set_start (const double& w) {
-               set_beat (w);
-       }
-
        void update_bar_offset_from_bbt (const Meter&);
        void update_bbt_time_from_bar_offset (const Meter&);
        double bar_offset() const { return _bar_offset; }
@@ -243,7 +239,7 @@ class LIBARDOUR_API TempoMetric {
        void set_tempo (const Tempo& t)              { _tempo = &t; }
        void set_meter (const Meter& m)              { _meter = &m; }
        void set_frame (framepos_t f)                { _frame = f; }
-       void set_start (const double& t)             { _start = t; }
+       void set_beat (const double& t)              { _beat = t; }
 
        void set_metric (const MetricSection* section) {
                const MeterSection* meter;
@@ -255,19 +251,19 @@ class LIBARDOUR_API TempoMetric {
                }
 
                set_frame(section->frame());
-               set_start(section->start());
+               set_beat(section->beat());
        }
 
        const Meter&              meter() const { return *_meter; }
        const Tempo&              tempo() const { return *_tempo; }
        framepos_t                frame() const { return _frame; }
-       const double& start() const { return _start; }
+       const double&             beat() const { return _beat; }
 
   private:
        const Meter*       _meter;
        const Tempo*       _tempo;
        framepos_t         _frame;
-       double             _start;
+       double             _beat;
 };
 
 /** Tempo Map - mapping of timecode to musical time.
@@ -360,14 +356,14 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
        const MeterSection& meter_section_at (framepos_t) const;
 
        void add_tempo (const Tempo&, double where, TempoSection::Type type);
-       void add_meter (const Meter&, double start, Timecode::BBT_Time where);
+       void add_meter (const Meter&, double beat, Timecode::BBT_Time where);
 
        void remove_tempo (const TempoSection&, bool send_signal);
        void remove_meter (const MeterSection&, bool send_signal);
 
        void replace_tempo (const TempoSection&, const Tempo&, const double& where, TempoSection::Type type);
        void gui_set_tempo_frame (TempoSection&, framepos_t where, double beat);
-       void replace_meter (const MeterSection&, const Meter&, const double& start, const Timecode::BBT_Time& where);
+       void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where);
 
        framepos_t round_to_bar  (framepos_t frame, RoundMode dir);
        framepos_t round_to_beat (framepos_t frame, RoundMode dir);
@@ -404,8 +400,11 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
        PBD::Signal0<void> MetricPositionChanged;
 
        double bbt_to_beats (Timecode::BBT_Time bbt);
+       Timecode::BBT_Time beats_to_bbt (double beats);
 
 private:
+       double bbt_to_beats_unlocked (Timecode::BBT_Time bbt);
+       Timecode::BBT_Time beats_to_bbt_unlocked (double beats);
 
        friend class ::BBTTest;
        friend class ::FrameposPlusBeatsTest;
@@ -427,12 +426,10 @@ private:
        const TempoSection& first_tempo() const;
        TempoSection&       first_tempo();
 
-       Timecode::BBT_Time beats_to_bbt (double beats);
-
        void do_insert (MetricSection* section);
 
        void add_tempo_locked (const Tempo&, double where, bool recompute, TempoSection::Type type);
-       void add_meter_locked (const Meter&, double start, Timecode::BBT_Time where, bool recompute);
+       void add_meter_locked (const Meter&, double beat, Timecode::BBT_Time where, bool recompute);
 
        bool remove_tempo_locked (const TempoSection&);
        bool remove_meter_locked (const MeterSection&);
index 580c1b60db69d588a5a7f61271ed0b208aa62b28..6dd24b748f870c6185a5f1bad4ebbd44fcd4fa06 100644 (file)
@@ -2342,7 +2342,7 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
                                                ++m;
                                        } else {
                                                tmetric.set_metric(metric);
-                                               bbt = metric->start();
+                                               bbt = tmap.beats_to_bbt (metric->beat());
                                                write_position(&_impl->forge, _ev_buffers[port_index],
                                                               tmetric, bbt, _session.transport_speed(),
                                                               metric->frame(),
index e9bbaa5c4a06f2421ae258bef10bfe3f6b534665..0f3beee8b1da20bdd659763e5530699a871b9c82 100644 (file)
@@ -5440,7 +5440,7 @@ Session::tempo_map_changed (const PropertyChange&)
 void
 Session::gui_tempo_map_changed ()
 {
-       //clear_clicks (); ?
+       clear_clicks ();
 
        playlists->update_after_tempo_map_change ();
 
index eebd47ab89e7d67e28f60decf67fb6f9fe90c7da..553f7ab1de34d763988eca4fc1c471bac438e9bd 100644 (file)
@@ -74,26 +74,35 @@ TempoSection::TempoSection (const XMLNode& node)
        : MetricSection (0.0), Tempo (TempoMap::default_tempo())
 {
        const XMLProperty *prop;
-       BBT_Time start;
        LocaleGuard lg;
-
-       if ((prop = node.property ("start")) == 0) {
-               error << _("MeterSection XML node has no \"start\" property") << endmsg;
-               throw failed_constructor();
+       BBT_Time bbt;
+       double beat;
+
+       if ((prop = node.property ("start")) != 0) {
+               if (sscanf (prop->value().c_str(), "%" PRIu32 "|%" PRIu32 "|%" PRIu32,
+                           &bbt.bars,
+                           &bbt.beats,
+                           &bbt.ticks) == 3) {
+                       /* legacy session - start used to be in bbt*/
+                       _legacy_bbt = bbt;
+                       beat = -1.0;
+                       set_beat (beat);
+               }
+       } else {
+               error << _("TempoSection XML node has no \"start\" property") << endmsg;
        }
 
-       if (sscanf (prop->value().c_str(), "%" PRIu32 "|%" PRIu32 "|%" PRIu32,
-                   &bbt.bars,
-                   &bbt.beats,
-                   &bbt.ticks) == 3) {
-               /* legacy session - start used to be in bbt*/
-               _legacy_bbt = bbt;
-               start = -1.0;
-       } else if (sscanf (prop->value().c_str(), "%lf", &start) != 1 || start < 0.0) {
-               error << _("TempoSection XML node has an illegal \"start\" value") << endmsg;
+
+       if ((prop = node.property ("beat")) != 0) {
+               if (sscanf (prop->value().c_str(), "%lf", &beat) != 1 || beat < 0.0) {
+                       error << _("TempoSection XML node has an illegal \"beat\" value") << endmsg;
+               } else {
+                       set_beat (beat);
+               }
+       } else {
+               error << _("TempoSection XML node has no \"beat\" property") << endmsg;
        }
 
-       set_start (start);
 
        if ((prop = node.property ("beats-per-minute")) == 0) {
                error << _("TempoSection XML node has no \"beats-per-minute\" property") << endmsg;
@@ -150,7 +159,7 @@ TempoSection::get_state() const
        LocaleGuard lg;
 
        snprintf (buf, sizeof (buf), "%f", beat());
-       root->add_property ("start", buf);
+       root->add_property ("beat", buf);
        snprintf (buf, sizeof (buf), "%f", _beats_per_minute);
        root->add_property ("beats-per-minute", buf);
        snprintf (buf, sizeof (buf), "%f", _note_type);
@@ -170,10 +179,10 @@ void
 
 TempoSection::update_bar_offset_from_bbt (const Meter& m)
 {
-       _bar_offset = (start() * BBT_Time::ticks_per_beat) /
+       _bar_offset = (beat() * BBT_Time::ticks_per_beat) /
                (m.divisions_per_bar() * BBT_Time::ticks_per_beat);
 
-       DEBUG_TRACE (DEBUG::TempoMath, string_compose ("Tempo set bar offset to %1 from %2 w/%3\n", _bar_offset, start(), m.divisions_per_bar()));
+       DEBUG_TRACE (DEBUG::TempoMath, string_compose ("Tempo set bar offset to %1 from %2 w/%3\n", _bar_offset, beat(), m.divisions_per_bar()));
 }
 
 void
@@ -328,22 +337,22 @@ TempoSection::time_at_beat (double beat, double end_tpm, double end_time) const
 void
 TempoSection::update_bbt_time_from_bar_offset (const Meter& meter)
 {
-       double new_start;
+       double new_beat;
 
        if (_bar_offset < 0.0) {
                /* not set yet */
                return;
        }
 
-       new_start = start();
+       new_beat = beat();
 
        double ticks = BBT_Time::ticks_per_beat * meter.divisions_per_bar() * _bar_offset;
-       new_start = ticks / BBT_Time::ticks_per_beat;
+       new_beat = ticks / BBT_Time::ticks_per_beat;
 
        DEBUG_TRACE (DEBUG::TempoMath, string_compose ("from bar offset %1 and dpb %2, ticks = %3->%4 beats = %5\n",
-                                                      _bar_offset, meter.divisions_per_bar(), ticks, new_start, new_start));
+                                                      _bar_offset, meter.divisions_per_bar(), ticks, new_beat, new_beat));
 
-       set_start (new_start);
+       set_beat (new_beat);
 }
 
 /***********************************************************************/
@@ -361,20 +370,28 @@ MeterSection::MeterSection (const XMLNode& node)
        double beat = 0.0;
        pair<double, BBT_Time> start;
 
-       if ((prop = node.property ("start")) == 0) {
-               error << _("MeterSection XML node has no \"start\" property") << endmsg;
-               throw failed_constructor();
-       }
-       if (sscanf (prop->value().c_str(), "%" PRIu32 "|%" PRIu32 "|%" PRIu32,
+       if ((prop = node.property ("start")) != 0) {
+               if (sscanf (prop->value().c_str(), "%" PRIu32 "|%" PRIu32 "|%" PRIu32,
                    &bbt.bars,
                    &bbt.beats,
-                   &bbt.ticks) == 3) {
-               /* legacy session - start used to be in bbt*/
-               beat = -1.0;
-       } else if (sscanf (prop->value().c_str(), "%lf", &beat) != 1 || beat < 0.0) {
-               error << _("MeterSection XML node has an illegal \"start\" value") << endmsg;
-               throw failed_constructor();
+                   &bbt.ticks) < 3) {
+                       error << _("MeterSection XML node has an illegal \"start\" value") << endmsg;
+               } else {
+                       /* legacy session - start used to be in bbt*/
+                       beat = -1.0;
+               }
+       } else {
+               error << _("MeterSection XML node has no \"start\" property") << endmsg;
+       }
+
+       if ((prop = node.property ("beat")) != 0) {
+               if (sscanf (prop->value().c_str(), "%lf", &beat) != 1 || beat < 0.0) {
+                       error << _("MeterSection XML node has an illegal \"beat\" value") << endmsg;
+               }
+       } else {
+               error << _("MeterSection XML node has no \"beat\" property") << endmsg;
        }
+
        start.first = beat;
 
        if ((prop = node.property ("bbt")) == 0) {
@@ -386,9 +403,10 @@ MeterSection::MeterSection (const XMLNode& node)
                error << _("MeterSection XML node has an illegal \"bbt\" value") << endmsg;
                throw failed_constructor();
        }
+
        start.second = bbt;
 
-       set_start (start);
+       set_beat (start);
 
        /* beats-per-bar is old; divisions-per-bar is new */
 
@@ -434,8 +452,8 @@ MeterSection::get_state() const
                  bbt().beats,
                  bbt().ticks);
        root->add_property ("bbt", buf);
-       snprintf (buf, sizeof (buf), "%lf", start());
-       root->add_property ("start", buf);
+       snprintf (buf, sizeof (buf), "%lf", beat());
+       root->add_property ("beat", buf);
        snprintf (buf, sizeof (buf), "%f", _note_type);
        root->add_property ("note-type", buf);
        snprintf (buf, sizeof (buf), "%f", _divisions_per_bar);
@@ -450,7 +468,7 @@ MeterSection::get_state() const
 
 struct MetricSectionSorter {
     bool operator() (const MetricSection* a, const MetricSection* b) {
-           return a->start() < b->start();
+           return a->beat() < b->beat();
     }
 };
 
@@ -580,13 +598,13 @@ TempoMap::do_insert (MetricSection* section)
 
                if ((m->bbt().beats != 1) || (m->bbt().ticks != 0)) {
 
-                       pair<double, BBT_Time> corrected = make_pair (m->start(), m->bbt());
+                       pair<double, BBT_Time> corrected = make_pair (m->beat(), m->bbt());
                        corrected.second.beats = 1;
                        corrected.second.ticks = 0;
-                       corrected.first = bbt_to_beats (corrected.second);
+                       corrected.first = bbt_to_beats_unlocked (corrected.second);
                        warning << string_compose (_("Meter changes can only be positioned on the first beat of a bar. Moving from %1 to %2"),
                                                   m->bbt(), corrected.second) << endmsg;
-                       m->set_start (corrected);
+                       m->set_beat (corrected);
                }
        }
 
@@ -608,7 +626,7 @@ TempoMap::do_insert (MetricSection* section)
 
                        /* Tempo sections */
 
-                       if (tempo->start() == insert_tempo->start()) {
+                       if (tempo->beat() == insert_tempo->beat()) {
 
                                if (!tempo->movable()) {
 
@@ -630,7 +648,7 @@ TempoMap::do_insert (MetricSection* section)
                        /* Meter Sections */
                        MeterSection* const meter = dynamic_cast<MeterSection*> (*i);
                        MeterSection* const insert_meter = dynamic_cast<MeterSection*> (section);
-                       if (meter->start() == insert_meter->start()) {
+                       if (meter->beat() == insert_meter->beat()) {
 
                                if (!meter->movable()) {
 
@@ -666,7 +684,7 @@ TempoMap::do_insert (MetricSection* section)
                        for (i = metrics.begin(); i != metrics.end(); ++i) {
                                MeterSection* const meter = dynamic_cast<MeterSection*> (*i);
 
-                               if (meter && meter->start() > insert_meter->start()) {
+                               if (meter && meter->beat() > insert_meter->beat()) {
                                        break;
                                }
                        }
@@ -675,7 +693,7 @@ TempoMap::do_insert (MetricSection* section)
                                TempoSection* const tempo = dynamic_cast<TempoSection*> (*i);
 
                                if (tempo) {
-                                       if (tempo->start() > insert_tempo->start()) {
+                                       if (tempo->beat() > insert_tempo->beat()) {
                                                break;
                                        }
                                }
@@ -693,7 +711,7 @@ TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const doubl
                Glib::Threads::RWLock::WriterLock lm (lock);
                TempoSection& first (first_tempo());
 
-               if (ts.start() != first.start()) {
+               if (ts.beat() != first.beat()) {
                        remove_tempo_locked (ts);
                        add_tempo_locked (tempo, where, true, type);
                } else {
@@ -719,7 +737,7 @@ TempoMap::gui_set_tempo_frame (TempoSection& ts, framepos_t frame, double  beat_
                //if (ts.position_lock_style() == MusicTime) {
                if (0) {
                        /* MusicTime */
-                       ts.set_start (beat_where);
+                       ts.set_beat (beat_where);
                        MetricSectionSorter cmp;
                        metrics.sort (cmp);
                } else {
@@ -759,23 +777,23 @@ TempoMap::gui_set_tempo_frame (TempoSection& ts, framepos_t frame, double  beat_
                        if (prev_ts) {
                                /* set the start beat */
                                double beats_to_ts = prev_ts->beat_at_frame (frame - prev_ts->frame(), ts.beats_per_minute(), frame - prev_ts->frame(), _frame_rate);
-                               double beats = beats_to_ts + prev_ts->start();
+                               double beats = beats_to_ts + prev_ts->beat();
 
                                if (next_ts) {
-                                       if (next_ts->start() < beats) {
+                                       if (next_ts->beat() < beats) {
                                                /* with frame-based editing, it is possible to get in a
                                                   situation where if the tempo was placed at the mouse pointer frame,
                                                   the following music-based tempo would jump to an earlier frame,
-                                                  changing the start beat of the moved tempo.
+                                                  changing the beat beat of the moved tempo.
                                                   in this case, we have to do some beat-based comparison TODO
                                                */
-                                       } else if (prev_ts->start() > beats) {
-                                               ts.set_start (prev_ts->start());
+                                       } else if (prev_ts->beat() > beats) {
+                                               ts.set_beat (prev_ts->beat());
                                        } else {
-                                               ts.set_start (beats);
+                                               ts.set_beat (beats);
                                        }
                                } else {
-                                       ts.set_start (beats);
+                                       ts.set_beat (beats);
                                }
                                MetricSectionSorter cmp;
                                metrics.sort (cmp);
@@ -813,14 +831,14 @@ TempoMap::add_tempo_locked (const Tempo& tempo, double where, bool recompute, AR
 }
 
 void
-TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const double& start, const BBT_Time& where)
+TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const BBT_Time& where)
 {
        {
                Glib::Threads::RWLock::WriterLock lm (lock);
                MeterSection& first (first_meter());
-               if (ms.start() != first.start()) {
+               if (ms.beat() != first.beat()) {
                        remove_meter_locked (ms);
-                       add_meter_locked (meter, start, where, true);
+                       add_meter_locked (meter, bbt_to_beats_unlocked (where), where, true);
                } else {
                        /* cannot move the first meter section */
                        *static_cast<Meter*>(&first) = meter;
@@ -832,11 +850,11 @@ TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const doubl
 }
 
 void
-TempoMap::add_meter (const Meter& meter, double start, BBT_Time where)
+TempoMap::add_meter (const Meter& meter, double beat, BBT_Time where)
 {
        {
                Glib::Threads::RWLock::WriterLock lm (lock);
-               add_meter_locked (meter, start, where, true);
+               add_meter_locked (meter, beat, where, true);
        }
 
 
@@ -850,7 +868,7 @@ TempoMap::add_meter (const Meter& meter, double start, BBT_Time where)
 }
 
 void
-TempoMap::add_meter_locked (const Meter& meter, double start, BBT_Time where, bool recompute)
+TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, bool recompute)
 {
        /* a new meter always starts a new bar on the first beat. so
           round the start time appropriately. remember that
@@ -867,7 +885,7 @@ TempoMap::add_meter_locked (const Meter& meter, double start, BBT_Time where, bo
        /* new meters *always* start on a beat. */
        where.ticks = 0;
 
-       do_insert (new MeterSection (start, where, meter.divisions_per_bar(), meter.note_divisor()));
+       do_insert (new MeterSection (beat, where, meter.divisions_per_bar(), meter.note_divisor()));
 
        if (recompute) {
                recompute_map (true);
@@ -1043,7 +1061,7 @@ TempoMap::recompute_map (bool reassign_tempo_bbt, framepos_t end)
                if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
 
                        if (prev_ts) {
-                               double const beats_relative_to_prev_ts = t->start() - prev_ts->start();
+                               double const beats_relative_to_prev_ts = t->beat() - prev_ts->beat();
                                double const ticks_relative_to_prev_ts = beats_relative_to_prev_ts * BBT_Time::ticks_per_beat;
 
                                /* assume (falsely) that the target tempo is constant */
@@ -1079,7 +1097,7 @@ TempoMap::recompute_map (bool reassign_tempo_bbt, framepos_t end)
        for (mi = metrics.begin(); mi != metrics.end(); ++mi) {
                /* we can do this beacuse we have the tempo section frames set */
                if ((meter = dynamic_cast<MeterSection*> (*mi)) != 0) {
-                       meter->set_frame (frame_at_tick (meter->start() * BBT_Time::ticks_per_beat));
+                       meter->set_frame (frame_at_tick (meter->beat() * BBT_Time::ticks_per_beat));
                }
        }
 }
@@ -1155,11 +1173,18 @@ TempoMap::bbt_time (framepos_t frame, BBT_Time& bbt)
                warning << string_compose (_("tempo map asked for BBT time at frame %1\n"), frame) << endmsg;
                return;
        }
-       bbt = beats_to_bbt (beat_at_frame (frame));
+       bbt = beats_to_bbt_unlocked (beat_at_frame (frame));
 }
 
 double
 TempoMap::bbt_to_beats (Timecode::BBT_Time bbt)
+{
+       Glib::Threads::RWLock::ReaderLock lm (lock);
+       return bbt_to_beats_unlocked (bbt);
+}
+
+double
+TempoMap::bbt_to_beats_unlocked (Timecode::BBT_Time bbt)
 {
        /* CALLER HOLDS READ LOCK */
 
@@ -1174,13 +1199,13 @@ TempoMap::bbt_to_beats (Timecode::BBT_Time bbt)
                if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
                        double bars_to_m = 0.0;
                        if (prev_ms) {
-                               bars_to_m = (m->start() - prev_ms->start()) / prev_ms->divisions_per_bar();
+                               bars_to_m = (m->beat() - prev_ms->beat()) / prev_ms->divisions_per_bar();
                        }
                        if ((bars_to_m + accumulated_bars) > (bbt.bars - 1)) {
                                break;
                        }
                        if (prev_ms) {
-                               accumulated_beats += m->start() - prev_ms->start();
+                               accumulated_beats += m->beat() - prev_ms->beat();
                                accumulated_bars += bars_to_m;
                        }
                        prev_ms = m;
@@ -1189,13 +1214,19 @@ TempoMap::bbt_to_beats (Timecode::BBT_Time bbt)
 
        double const remaining_bars = (bbt.bars - 1) - accumulated_bars;
        double const remaining_bars_in_beats = remaining_bars * prev_ms->divisions_per_bar();
-       double const ret = remaining_bars_in_beats + accumulated_beats + (bbt.ticks / BBT_Time::ticks_per_beat);
-
+       double const ret = remaining_bars_in_beats + accumulated_beats + (bbt.beats - 1) + (bbt.ticks / BBT_Time::ticks_per_beat);
        return ret;
 }
 
 Timecode::BBT_Time
 TempoMap::beats_to_bbt (double beats)
+{
+       Glib::Threads::RWLock::ReaderLock lm (lock);
+       return beats_to_bbt_unlocked (beats);
+}
+
+Timecode::BBT_Time
+TempoMap::beats_to_bbt_unlocked (double beats)
 {
        /* CALLER HOLDS READ LOCK */
 
@@ -1209,21 +1240,21 @@ TempoMap::beats_to_bbt (double beats)
 
                if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
 
-                       if (beats < m->start()) {
+                       if (beats < m->beat()) {
                                /* this is the meter after the one our beat is on*/
                                break;
                        }
 
                        if (prev_ms) {
                                /* we need a whole number of bars. */
-                               accumulated_bars += ((m->start() - prev_ms->start()) + 1) / prev_ms->divisions_per_bar();
+                               accumulated_bars += ((m->beat() - prev_ms->beat()) + 1) / prev_ms->divisions_per_bar();
                        }
 
                        prev_ms = m;
                }
        }
 
-       double const beats_in_ms = beats - prev_ms->start();
+       double const beats_in_ms = beats - prev_ms->beat();
        uint32_t const bars_in_ms = (uint32_t) floor (beats_in_ms / prev_ms->divisions_per_bar());
        uint32_t const total_bars = bars_in_ms + accumulated_bars;
        double const remaining_beats = beats_in_ms - (bars_in_ms * prev_ms->divisions_per_bar());
@@ -1362,7 +1393,7 @@ TempoMap::frame_time (const BBT_Time& bbt)
        }
        Glib::Threads::RWLock::ReaderLock lm (lock);
 
-       framepos_t const ret = frame_at_beat (bbt_to_beats (bbt));
+       framepos_t const ret = frame_at_beat (bbt_to_beats_unlocked (bbt));
 
        return ret;
 }
@@ -1521,7 +1552,7 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
 
        double const beat_at_framepos = beat_at_frame (frame);
 
-       BBT_Time bbt (beats_to_bbt (beat_at_framepos));
+       BBT_Time bbt (beats_to_bbt_unlocked (beat_at_framepos));
 
        switch (type) {
        case Bar:
@@ -1581,7 +1612,7 @@ TempoMap::get_grid (vector<TempoMap::BBTPoint>& points,
                framecnt_t const pos = frame_at_beat (cnt);
                MeterSection const meter = meter_section_at (pos);
                Tempo const tempo = tempo_at (pos);
-               BBT_Time const bbt = beats_to_bbt ((double) cnt);
+               BBT_Time const bbt = beats_to_bbt_unlocked ((double) cnt);
 
                points.push_back (BBTPoint (meter, tempo, pos, bbt.bars, bbt.beats));
                ++cnt;
@@ -1790,15 +1821,15 @@ TempoMap::set_state (const XMLNode& node, int /*version*/)
                        MeterSection* prev_ms;
                        TempoSection* prev_ts;
                        if ((prev_ms = dynamic_cast<MeterSection*>(*i)) != 0) {
-                               if (prev_ms->start() < 0.0) {
+                               if (prev_ms->beat() < 0.0) {
                                        /*XX we cannot possibly make this work??. */
                                        pair<double, BBT_Time> start = make_pair (((prev_ms->bbt().bars - 1) * 4.0) + (prev_ms->bbt().beats - 1) + (prev_ms->bbt().ticks / BBT_Time::ticks_per_beat), prev_ms->bbt());
-                                       prev_ms->set_start (start);
+                                       prev_ms->set_beat (start);
                                }
                        } else if ((prev_ts = dynamic_cast<TempoSection*>(*i)) != 0) {
-                               if (prev_ts->start() < 0.0) {
+                               if (prev_ts->beat() < 0.0) {
                                        double const start = ((prev_ts->legacy_bbt().bars - 1) * 4.0) + (prev_ts->legacy_bbt().beats - 1) + (prev_ts->legacy_bbt().ticks / BBT_Time::ticks_per_beat);
-                                       prev_ts->set_start (start);
+                                       prev_ts->set_beat (start);
 
                                }
                        }
@@ -1815,15 +1846,15 @@ TempoMap::set_state (const XMLNode& node, int /*version*/)
                                TempoSection* ts;
                                TempoSection* prev_ts;
                                if ((prev_ms = dynamic_cast<MeterSection*>(*prev)) != 0 && (ms = dynamic_cast<MeterSection*>(*i)) != 0) {
-                                       if (prev_ms->start() == ms->start()) {
-                                               cerr << string_compose (_("Multiple meter definitions found at %1"), prev_ms->start()) << endmsg;
-                                               error << string_compose (_("Multiple meter definitions found at %1"), prev_ms->start()) << endmsg;
+                                       if (prev_ms->beat() == ms->beat()) {
+                                               cerr << string_compose (_("Multiple meter definitions found at %1"), prev_ms->beat()) << endmsg;
+                                               error << string_compose (_("Multiple meter definitions found at %1"), prev_ms->beat()) << endmsg;
                                                return -1;
                                        }
                                } else if ((prev_ts = dynamic_cast<TempoSection*>(*prev)) != 0 && (ts = dynamic_cast<TempoSection*>(*i)) != 0) {
-                                       if (prev_ts->start() == ts->start()) {
-                                               cerr << string_compose (_("Multiple tempo definitions found at %1"), prev_ts->start()) << endmsg;
-                                               error << string_compose (_("Multiple tempo definitions found at %1"), prev_ts->start()) << endmsg;
+                                       if (prev_ts->beat() == ts->beat()) {
+                                               cerr << string_compose (_("Multiple tempo definitions found at %1"), prev_ts->beat()) << endmsg;
+                                               error << string_compose (_("Multiple tempo definitions found at %1"), prev_ts->beat()) << endmsg;
                                                return -1;
                                        }
                                }
@@ -1849,7 +1880,7 @@ TempoMap::dump (std::ostream& o) const
        for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
 
                if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
-                       o << "Tempo @ " << *i << " (Bar-offset: " << t->bar_offset() << ") " << t->beats_per_minute() << " BPM (pulse = 1/" << t->note_type() << ") at " << t->start() << " frame= " << t->frame() << " (movable? "
+                       o << "Tempo @ " << *i << " (Bar-offset: " << t->bar_offset() << ") " << t->beats_per_minute() << " BPM (pulse = 1/" << t->note_type() << ") at " << t->beat() << " frame= " << t->frame() << " (movable? "
                          << t->movable() << ')' << endl;
                } else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
                        o << "Meter @ " << *i << ' ' << m->divisions_per_bar() << '/' << m->note_divisor() << " at " << m->bbt() << " frame= " << m->frame()
@@ -1930,22 +1961,22 @@ TempoMap::insert_time (framepos_t where, framecnt_t amount)
                        if (prev) {
                                if (ts){
                                        if ((t = dynamic_cast<TempoSection*>(prev)) != 0) {
-                                               ts->set_start (t->start());
+                                               ts->set_beat (t->beat());
                                        }
                                        if ((m = dynamic_cast<MeterSection*>(prev)) != 0) {
-                                               ts->set_start (m->start());
+                                               ts->set_beat (m->beat());
                                        }
                                        ts->set_frame (prev->frame());
 
                                }
                                if (ms) {
                                        if ((m = dynamic_cast<MeterSection*>(prev)) != 0) {
-                                               pair<double, BBT_Time> start = make_pair (m->start(), m->bbt());
-                                               ms->set_start (start);
+                                               pair<double, BBT_Time> start = make_pair (m->beat(), m->bbt());
+                                               ms->set_beat (start);
                                        }
                                        if ((t = dynamic_cast<TempoSection*>(prev)) != 0) {
-                                               pair<double, BBT_Time> start = make_pair (t->start(), beats_to_bbt (t->start()));
-                                               ms->set_start (start);
+                                               pair<double, BBT_Time> start = make_pair (t->beat(), beats_to_bbt_unlocked (t->beat()));
+                                               ms->set_beat (start);
                                        }
                                        ms->set_frame (prev->frame());
                                }
@@ -1958,9 +1989,9 @@ TempoMap::insert_time (framepos_t where, framecnt_t amount)
                        // cerr << bbt << endl;
 
                        if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
-                               t->set_start (beat_at_frame (m->frame()));
+                               t->set_beat (beat_at_frame (m->frame()));
                                tempo = t;
-                               // cerr << "NEW TEMPO, frame = " << (*i)->frame() << " start = " << (*i)->start() <<endl;
+                               // cerr << "NEW TEMPO, frame = " << (*i)->frame() << " beat = " << (*i)->beat() <<endl;
                        } else if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
                                bbt_time (m->frame(), bbt);
 
@@ -1984,9 +2015,9 @@ TempoMap::insert_time (framepos_t where, framecnt_t amount)
                                        }
                                }
                                pair<double, BBT_Time> start = make_pair (beat_at_frame (m->frame()), bbt);
-                               m->set_start (start);
+                               m->set_beat (start);
                                meter = m;
-                               // cerr << "NEW METER, frame = " << (*i)->frame() << " start = " << (*i)->start() <<endl;
+                               // cerr << "NEW METER, frame = " << (*i)->frame() << " beat = " << (*i)->beat() <<endl;
                        } else {
                                fatal << _("programming error: unhandled MetricSection type") << endmsg;
                                abort(); /*NOTREACHED*/