diff options
author | nick_m <mainsbridge@gmail.com> | 2017-03-01 01:58:53 +1100 |
---|---|---|
committer | nick_m <mainsbridge@gmail.com> | 2017-03-01 01:58:53 +1100 |
commit | 38b5d887950e72a65341d616bf40195657228271 (patch) | |
tree | 4458a00751af2460e02711495d6a0cb18616ca64 | |
parent | a9bb1afb27e90466f1fd73372f1c016401148cac (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.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor_markers.cc | 34 | ||||
-rw-r--r-- | libs/ardour/ardour/tempo.h | 1 | ||||
-rw-r--r-- | libs/ardour/tempo.cc | 37 |
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) { |