diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2012-01-04 02:49:01 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2012-01-04 02:49:01 +0000 |
commit | b1a33855ce4254ebbee4f273bb74ceb50628ed05 (patch) | |
tree | 01dffa7f7b41545e45fe6cda8787cdac507a3edc | |
parent | 10d9eaf0bd0f40d5bd272268dbac20908557ad71 (diff) |
use BBTPoint::is_bar() rather than ::beat == 1 ; implement TempoMap::framepos_plus_{beats,bbt}() with new map structure (not totally finished or accurate yet); prevent crash when dragging a marker to replace the initial tempo/meter markers
git-svn-id: svn://localhost/ardour2/branches/3.0@11154 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | gtk2_ardour/editor_rulers.cc | 16 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 5 | ||||
-rw-r--r-- | gtk2_ardour/tempo_lines.cc | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/tempo.h | 2 | ||||
-rw-r--r-- | libs/ardour/tempo.cc | 264 |
5 files changed, 87 insertions, 202 deletions
diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc index d97debbc66..c9fb7fc65d 100644 --- a/gtk2_ardour/editor_rulers.cc +++ b/gtk2_ardour/editor_rulers.cc @@ -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; diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 0437b4b938..d26e9b1323 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -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; } diff --git a/gtk2_ardour/tempo_lines.cc b/gtk2_ardour/tempo_lines.cc index 9d590780ce..2c7895f7a8 100644 --- a/gtk2_ardour/tempo_lines.cc +++ b/gtk2_ardour/tempo_lines.cc @@ -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) { diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index 0ca3b71ec7..b8b64fa37f 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -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) {} diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 1f204ef4e0..3ca314a0da 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -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, |