use BBTPoint::is_bar() rather than ::beat == 1 ; implement TempoMap::framepos_plus_...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 4 Jan 2012 02:49:01 +0000 (02:49 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 4 Jan 2012 02:49:01 +0000 (02:49 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@11154 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/editor_rulers.cc
gtk2_ardour/midi_region_view.cc
gtk2_ardour/tempo_lines.cc
libs/ardour/ardour/tempo.h
libs/ardour/tempo.cc

index d97debbc66f31ca99aa35122cafb0f1363c7813d..c9fb7fc65d4be6c7cdbc037c9f672426c9ab0b55 100644 (file)
@@ -1316,7 +1316,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble /*upp
                                helper_active = true;
                        } else {
 
-                               if ((*i).beat == 1) {
+                               if ((*i).is_bar()) {
                                        (*marks)[n].style = GtkCustomRulerMarkMajor;
                                        snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
                                } else if (((*i).beat % 2 == 1)) {
@@ -1353,7 +1353,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble /*upp
                                helper_active = true;
                        } else {
 
-                               if ((*i).beat == 1) {
+                               if ((*i).is_bar()) {
                                        (*marks)[n].style = GtkCustomRulerMarkMajor;
                                        snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
                                } else {
@@ -1443,7 +1443,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble /*upp
                                helper_active = true;
                        } else {
 
-                               if ((*i).beat == 1) {
+                               if ((*i).is_bar()) {
                                        (*marks)[n].style = GtkCustomRulerMarkMajor;
                                        snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
                                } else {
@@ -1538,7 +1538,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble /*upp
                                  helper_active = true;
                        } else {
 
-                                 if ((*i).beat == 1) {
+                                 if ((*i).is_bar()) {
                                          (*marks)[n].style = GtkCustomRulerMarkMajor;
                                          snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
                                  } else {
@@ -1628,7 +1628,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble /*upp
                        bbt_nmarks = (gint) (bbt_bars / 64) + 1;
                        *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
                        for (n = 0,   i = current_bbt_points_begin; i != current_bbt_points_end && n < bbt_nmarks; i++) {
-                               if ((*i).beat == 1) {
+                               if ((*i).is_bar()) {
                                        if ((*i).bar % 64 == 1) {
                                                if ((*i).bar % 256 == 1) {
                                                        snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
@@ -1653,7 +1653,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble /*upp
                        bbt_nmarks = (bbt_bars / 16) + 1;
                *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
                for (n = 0,  i = current_bbt_points_begin; i != current_bbt_points_end && n < bbt_nmarks; i++) {
-                       if ((*i).beat == 1) {
+                       if ((*i).is_bar()) {
                          if ((*i).bar % 16 == 1) {
                                if ((*i).bar % 64 == 1) {
                                        snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
@@ -1678,7 +1678,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble /*upp
                bbt_nmarks = (bbt_bars / 4) + 1;
                *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
                for (n = 0,   i = current_bbt_points_begin; i != current_bbt_points_end && n < bbt_nmarks; ++i) {
-                       if ((*i).beat == 1) {
+                       if ((*i).is_bar()) {
                          if ((*i).bar % 4 == 1) {
                                if ((*i).bar % 16 == 1) {
                                        snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
@@ -1704,7 +1704,7 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble /*upp
                bbt_nmarks = bbt_bars + 2;
                *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks );
                for (n = 0,  i = current_bbt_points_begin; i != current_bbt_points_end && n < bbt_nmarks; i++) {
-                       if ((*i).beat == 1) {
+                       if ((*i).is_bar()) {
                          if ((*i).bar % 4 == 1) {
                                        snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
                                        (*marks)[n].style = GtkCustomRulerMarkMajor;
index 0437b4b938bb61fe7ada657edff39543e502fbf6..d26e9b1323ce62f335b214237da4df244953e095 100644 (file)
@@ -2303,8 +2303,13 @@ MidiRegionView::note_dropped(CanvasNoteEvent *, frameoffset_t dt, int8_t dnote)
 
        for (Selection::iterator i = _selection.begin(); i != _selection.end() ; ++i) {
 
+               cerr << "Note dropped, was at " << (*i)->note()->time() << " now + " << dt << endl;
+               cerr << "original pos as frames " << source_beats_to_absolute_frames ((*i)->note()->time()) << endl;
+               
                Evoral::MusicalTime new_time = absolute_frames_to_source_beats (source_beats_to_absolute_frames ((*i)->note()->time()) + dt);
 
+               cerr << "new time in beats = " << new_time << endl;
+
                if (new_time < 0) {
                        continue;
                }
index 9d590780ce958ab0170ef2cd2b8219e631373b9a..2c7895f7a8a43dfbafa15a3975c19dd3e9e0170f 100644 (file)
@@ -133,7 +133,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
 
        for (i = begin; i != end; ++i) {
 
-               if ((*i).beat == 1) {
+               if ((*i).is_bar()) {
                        color = ARDOUR_UI::config()->canvasvar_MeasureLineBar.get();
                } else {
                        if (beat_density > 2.0) {
index 0ca3b71ec7603c68bbb3b6aada31f455b410c8c0..b8b64fa37f351e7702fded23896457c13bdecec4 100644 (file)
@@ -213,6 +213,8 @@ class TempoMap : public PBD::StatefulDestructible
             operator Timecode::BBT_Time() const { return bbt(); }
             operator framepos_t() const { return frame; }
             
+           bool is_bar() const { return beat == 1; }
+
             BBTPoint (const Meter& m, const Tempo& t, framepos_t f,
                       uint32_t b, uint32_t e)
                     : frame (f), meter (&m), tempo (&t), bar (b), beat (e) {}
index 1f204ef4e0fc516cbf99296955ecc511ac55f2c4..3ca314a0da1ba8b6e8b4401f895154d82cc64d6b 100644 (file)
@@ -372,6 +372,7 @@ TempoMap::do_insert (MetricSection* section)
        /* CALLER MUST HOLD WRITE LOCK */
 
        bool reassign_tempo_bbt = false;
+       bool need_add = true;
 
        assert (section->start().ticks == 0);
 
@@ -422,10 +423,25 @@ TempoMap::do_insert (MetricSection* section)
                }
 
                /* hacky comparison of type */
-               bool const a = dynamic_cast<TempoSection*> (*i) != 0;
-               bool const b = dynamic_cast<TempoSection*> (section) != 0;
+               bool const iter_is_tempo = dynamic_cast<TempoSection*> (*i) != 0;
+               bool const insert_is_tempo = dynamic_cast<TempoSection*> (section) != 0;
+
+               if (iter_is_tempo == insert_is_tempo) {
+
+                       if (!(*i)->movable()) {
+
+                               /* can't (re)move this section, so overwrite it
+                                */
+
+                               if (!iter_is_tempo) {
+                                       *(dynamic_cast<MeterSection*>(*i)) = *(dynamic_cast<MeterSection*>(section));
+                               } else {
+                                       *(dynamic_cast<TempoSection*>(*i)) = *(dynamic_cast<TempoSection*>(section));
+                               }
+                               need_add = false;
+                               break;
+                       }
 
-               if (a == b) {
                        to_remove = i;
                        break;
                }
@@ -438,20 +454,22 @@ TempoMap::do_insert (MetricSection* section)
 
        /* Add the given MetricSection */
 
-       for (i = metrics->begin(); i != metrics->end(); ++i) {
-
-               if ((*i)->compare (*section) < 0) {
-                       continue;
+       if (need_add) {
+               for (i = metrics->begin(); i != metrics->end(); ++i) {
+                       
+                       if ((*i)->compare (*section) < 0) {
+                               continue;
+                       }
+                       
+                       metrics->insert (i, section);
+                       break;
                }
 
-               metrics->insert (i, section);
-               break;
+               if (i == metrics->end()) {
+                       metrics->insert (metrics->end(), section);
+               }
        }
 
-       if (i == metrics->end()) {
-               metrics->insert (metrics->end(), section);
-       }
-       
        recompute_map (reassign_tempo_bbt);
 }
 
@@ -1114,7 +1132,7 @@ TempoMap::bbt_duration_at_unlocked (const BBT_Time& when, const BBT_Time& bbt, i
 
        while (wi != _map.end() && bars < bbt.bars) {
                ++wi;
-               if ((*wi).beat == 1) {
+               if ((*wi).is_bar()) {
                        ++bars;
                }
        }
@@ -1290,11 +1308,11 @@ TempoMap::round_to_type (framepos_t frame, int dir, BBTPointType type)
                if (dir < 0) {
                        /* find bar previous to 'frame' */
 
-                       if ((*fi).beat == 1 && (*fi).frame == frame) {
+                       if ((*fi).is_bar() && (*fi).frame == frame) {
                                --fi;
                        }
 
-                       while ((*fi).beat > 1) {
+                       while (!(*fi).is_bar()) {
                                if (fi == _map.begin()) {
                                        break;
                                }
@@ -1308,11 +1326,11 @@ TempoMap::round_to_type (framepos_t frame, int dir, BBTPointType type)
 
                        /* find bar following 'frame' */
 
-                       if ((*fi).beat == 1 && (*fi).frame == frame) {
+                       if ((*fi).is_bar() && (*fi).frame == frame) {
                                ++fi;
                        }
 
-                       while ((*fi).beat != 1) {
+                       while (!(*fi).is_bar()) {
                                fi++;
                                if (fi == _map.end()) {
                                        --fi;
@@ -1607,67 +1625,7 @@ TempoMap::insert_time (framepos_t where, framecnt_t amount)
 framepos_t
 TempoMap::framepos_plus_beats (framepos_t pos, Evoral::MusicalTime beats)
 {
-       Metrics::const_iterator i;
-       const TempoSection* tempo;
-
-       /* Find the starting tempo */
-
-       for (i = metrics->begin(); i != metrics->end(); ++i) {
-
-               /* This is a bit of a hack, but pos could be -ve, and if it is,
-                  we consider the initial metric changes (at time 0) to actually
-                  be in effect at pos.
-               */
-               framepos_t f = (*i)->frame ();
-               if (pos < 0 && f == 0) {
-                       f = pos;
-               }
-
-               if (f > pos) {
-                       break;
-               }
-
-               const TempoSection* t;
-
-               if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
-                       tempo = t;
-               }
-       }
-
-       /* We now have:
-
-          tempo -> the Tempo for "pos"
-          i     -> for first new metric after "pos", possibly metrics->end()
-       */
-
-       while (beats) {
-
-               /* Distance to the end of this section in frames */
-               framecnt_t distance_frames = i == metrics->end() ? max_framepos : ((*i)->frame() - pos);
-
-               /* Distance to the end in beats */
-               Evoral::MusicalTime distance_beats = distance_frames / tempo->frames_per_beat (_frame_rate);
-
-               /* Amount to subtract this time */
-               double const sub = min (distance_beats, beats);
-
-               /* Update */
-               beats -= sub;
-               pos += sub * tempo->frames_per_beat (_frame_rate);
-
-               /* Move on if there's anything to move to */
-               if (i != metrics->end ()) {
-                       const TempoSection* t;
-                       
-                       if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
-                               tempo = t;
-                       }
-
-                       ++i;
-               }
-       }
-
-       return pos;
+       return framepos_plus_bbt (pos, BBT_Time (beats));
 }
 
 /** Subtract some (fractional) beats to a frame position, and return the result in frames */
@@ -1757,134 +1715,54 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats)
 framepos_t
 TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op)
 {
-       Metrics::const_iterator i;
-       const MeterSection* meter;
-       const MeterSection* m;
-       const TempoSection* tempo;
-       const TempoSection* t;
-       double frames_per_beat;
-
-       meter = &first_meter ();
-       tempo = &first_tempo ();
-
-       assert (meter);
-       assert (tempo);
+       BBT_Time op_copy (op);
+       int additional_minutes = 1;
+       BBTPointList::const_iterator i;
 
-       /* find the starting metrics for tempo & meter */
+       while (true) {
 
-       for (i = metrics->begin(); i != metrics->end(); ++i) {
-
-               if ((*i)->frame() > pos) {
-                       break;
-               }
+               i = bbt_before_or_at (pos);
+               
+               op = op_copy;
 
-               if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
-                       tempo = t;
-               } else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
-                       meter = m;
+               if ((*i).frame != pos) {
+                       /* we know that (*i).frame is before pos */
+                       cerr << "Need to account for offset of " << (pos - (*i).frame) << endl;
                }
-       }
 
-       /* We now have:
-
-          meter -> the Meter for "pos"
-          tempo -> the Tempo for "pos"
-          i     -> for first new metric after "pos", possibly metrics->end()
-       */
-
-       /* now comes the complicated part. we have to add one beat a time,
-          checking for a new metric on every beat.
-       */
-
-       frames_per_beat = tempo->frames_per_beat (_frame_rate);
-
-       uint64_t bars = 0;
-
-       while (op.bars) {
-
-               bars++;
-               op.bars--;
-
-               /* check if we need to use a new metric section: has adding frames moved us
-                  to or after the start of the next metric section? in which case, use it.
-               */
-
-               if (i != metrics->end()) {
-                       if ((*i)->frame() <= pos) {
-
-                               /* about to change tempo or meter, so add the
-                                * number of frames for the bars we've just
-                                * traversed before we change the
-                                * frames_per_beat value.
-                                */
-                               
-                               pos += llrint (frames_per_beat * (bars * meter->divisions_per_bar()));
-                               bars = 0;
-
-                               if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
-                                       tempo = t;
-                               } else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
-                                       meter = m;
+               while (i != _map.end() && (op.bars || op.beats)) {
+                       ++i;
+                       if ((*i).is_bar()) {
+                               if (op.bars) {
+                                       op.bars--;
+                               }
+                       } else {
+                               if (op.beats) {
+                                       op.beats--;
                                }
-                               ++i;
-                               frames_per_beat = tempo->frames_per_beat (_frame_rate);
-
                        }
                }
+               
+               if (i != _map.end()) {
+                       break;
+               }
 
-       }
-
-       pos += llrint (frames_per_beat * (bars * meter->divisions_per_bar()));
-
-       uint64_t beats = 0;
-
-       while (op.beats) {
-
-               /* given the current meter, have we gone past the end of the bar ? */
-
-               beats++;
-               op.beats--;
-
-               /* check if we need to use a new metric section: has adding frames moved us
-                  to or after the start of the next metric section? in which case, use it.
-               */
-
-               if (i != metrics->end()) {
-                       if ((*i)->frame() <= pos) {
-
-                               /* about to change tempo or meter, so add the
-                                * number of frames for the beats we've just
-                                * traversed before we change the
-                                * frames_per_beat value.
-                                */
+               /* we hit the end of the map before finish the bbt walk.
+                */
 
-                               pos += llrint (beats * frames_per_beat);
-                               beats = 0;
+               require_map_to (pos + (_frame_rate * 60 * additional_minutes));
+               additional_minutes *= 2;
 
-                               if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
-                                       tempo = t;
-                               } else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
-                                       meter = m;
-                               }
-                               ++i;
-                               frames_per_beat = tempo->frames_per_beat (_frame_rate);
-                       }
-               }
+               /* go back and try again */
+               cerr << "reached end of map with op now at " << op << " end = " << _map.back().frame << ' ' << _map.back().bar << '|' << _map.back().beat << ", trying to walk " << op_copy << " ... retry\n";
        }
-
-       pos += llrint (beats * frames_per_beat);
-
+       
        if (op.ticks) {
-               if (op.ticks >= BBT_Time::ticks_per_bar_division) {
-                       pos += llrint (frames_per_beat + /* extra beat */
-                                      (frames_per_beat * ((op.ticks % (uint32_t) BBT_Time::ticks_per_bar_division) / 
-                                                          (double) BBT_Time::ticks_per_bar_division)));
-               } else {
-                       pos += llrint (frames_per_beat * (op.ticks / (double) BBT_Time::ticks_per_bar_division));
-               }
+               return (*i).frame + 
+                       llrint ((*i).meter->frames_per_division (*(*i).tempo, _frame_rate) * (op.ticks/BBT_Time::ticks_per_bar_division));
+       } else {
+               return (*i).frame;
        }
-
-       return pos;
 }
 
 /** Count the number of beats that are equivalent to distance when going forward,