summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornick_m <mainsbridge@gmail.com>2017-03-01 01:58:53 +1100
committernick_m <mainsbridge@gmail.com>2017-03-01 01:58:53 +1100
commit38b5d887950e72a65341d616bf40195657228271 (patch)
tree4458a00751af2460e02711495d6a0cb18616ca64
parenta9bb1afb27e90466f1fd73372f1c016401148cac (diff)
allow continuation of tempo via right-click 'Continue' where appropriate.
- this is the opposite of 'Ramp to Next'. it removes discontinuities between the last end tempo and the current by altering the current one.
-rw-r--r--gtk2_ardour/editor.h1
-rw-r--r--gtk2_ardour/editor_markers.cc34
-rw-r--r--libs/ardour/ardour/tempo.h1
-rw-r--r--libs/ardour/tempo.cc37
4 files changed, 73 insertions, 0 deletions
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index c70ca4ae5f..88318c4f69 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -1688,6 +1688,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void rename_marker (ArdourMarker *marker);
void toggle_marker_lock_style ();
void toggle_tempo_type ();
+ void continue_previous_tempo ();
void ramp_to_next_tempo ();
void toggle_marker_menu_lock ();
void toggle_marker_menu_glue ();
diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc
index c2b09f171c..66911fc34c 100644
--- a/gtk2_ardour/editor_markers.cc
+++ b/gtk2_ardour/editor_markers.cc
@@ -1000,6 +1000,11 @@ Editor::build_tempo_marker_menu (TempoMarker* loc, bool can_remove)
items.push_back (MenuElem (_("Ramp to Next"), sigc::mem_fun(*this, &Editor::ramp_to_next_tempo)));
}
+ TempoSection* prev_ts = _session->tempo_map().previous_tempo_section (&loc->tempo());
+ if (prev_ts && prev_ts->end_note_types_per_minute() != loc->tempo().note_types_per_minute()) {
+ items.push_back (MenuElem (_("Continue"), sigc::mem_fun(*this, &Editor::continue_previous_tempo)));
+ }
+
if (loc->tempo().position_lock_style() == AudioTime && can_remove) {
items.push_back (MenuElem (_("Lock to Music"), sigc::mem_fun(*this, &Editor::toggle_marker_lock_style)));
} else if (can_remove) {
@@ -1461,6 +1466,35 @@ Editor::toggle_tempo_type ()
}
void
+Editor::continue_previous_tempo ()
+{
+ TempoMarker* tm;
+ MeterMarker* mm;
+ dynamic_cast_marker_object (marker_menu_item->get_data ("marker"), &mm, &tm);
+
+ if (tm) {
+ TempoMap& tmap (_session->tempo_map());
+ TempoSection* tsp = &tm->tempo();
+ TempoSection* prev_ts = tmap.previous_tempo_section (&tm->tempo());
+ if (prev_ts) {
+ const Tempo tempo (prev_ts->end_note_types_per_minute(), tsp->note_type(), tsp->end_note_types_per_minute());
+ const double pulse = tsp->pulse();
+ const framepos_t frame = tsp->frame();
+ const PositionLockStyle pls = tsp->position_lock_style();
+
+ begin_reversible_command (_("continue previous tempo"));
+ XMLNode &before = _session->tempo_map().get_state();
+
+ tmap.replace_tempo (*tsp, tempo, pulse, frame, pls);
+
+ XMLNode &after = _session->tempo_map().get_state();
+ _session->add_command(new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
+ commit_reversible_command ();
+ }
+ }
+}
+
+void
Editor::ramp_to_next_tempo ()
{
TempoMarker* tm;
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h
index 1426801f24..b1c2dc6428 100644
--- a/libs/ardour/ardour/tempo.h
+++ b/libs/ardour/ardour/tempo.h
@@ -367,6 +367,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
const MeterSection& meter_section_at_frame (framepos_t frame) const;
const MeterSection& meter_section_at_beat (double beat) const;
+ TempoSection* previous_tempo_section (TempoSection*) const;
TempoSection* next_tempo_section (TempoSection*) const;
/** add a tempo section locked to pls. ignored values will be set in recompute_tempi()
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 345d09b8bf..e11d28bd98 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -4286,6 +4286,43 @@ TempoMap::tempo_section_at_beat_locked (const Metrics& metrics, const double& be
}
TempoSection*
+TempoMap::previous_tempo_section (TempoSection* ts) const
+{
+ if (!ts) {
+ return 0;
+ }
+
+ Glib::Threads::RWLock::ReaderLock lm (lock);
+
+ TempoSection* prev = 0;
+
+ for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
+
+ if ((*i)->is_tempo()) {
+ TempoSection* t = static_cast<TempoSection*> (*i);
+
+ if (!t->active()) {
+ continue;
+ }
+
+ if (prev && t == ts) {
+
+ return prev;
+ }
+
+ prev = t;
+ }
+ }
+
+ if (prev == 0) {
+ fatal << endmsg;
+ abort(); /*NOTREACHED*/
+ }
+
+ return 0;
+}
+
+TempoSection*
TempoMap::next_tempo_section (TempoSection* ts) const
{
if (!ts) {