From fdd634f530b614c62c1566c9ff0545c56d56f59a Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sun, 29 May 2022 14:19:27 -0600 Subject: [PATCH] add ctrl-drag on tempo bar/ruler to adjust tempo more directly --- gtk2_ardour/editor.h | 1 + gtk2_ardour/editor_drag.cc | 77 +++++++++++++++++++++++++++++++++++++ gtk2_ardour/editor_drag.h | 19 +++++++++ gtk2_ardour/editor_mouse.cc | 7 +++- gtk2_ardour/tempo_curve.cc | 5 ++- 5 files changed, 106 insertions(+), 3 deletions(-) diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index d08d9a0681..3972fc76da 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -2493,6 +2493,7 @@ private: friend class BBTRulerDrag; friend class MeterMarkerDrag; friend class TempoMarkerDrag; + friend class TempoCurveDrag; friend class TempoTwistDrag; friend class TempoEndDrag; friend class CursorDrag; diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 151387fb2f..6dc65b96ca 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3530,6 +3530,83 @@ MeterMarkerDrag::aborted (bool moved) } +TempoCurveDrag::TempoCurveDrag (Editor* e, ArdourCanvas::Item* i) + : Drag (e, i, Temporal::BeatTime) +{ +} + +void +TempoCurveDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) +{ + Drag::start_grab (event, cursor); + /* setup thread-local tempo map ptr as a writable copy */ + map = _editor->begin_tempo_map_edit (); + TempoCurve* tc = reinterpret_cast (_item->get_data (X_("tempo curve"))); + if (!tc) { + point = const_cast (&map->tempo_at (raw_grab_time())); + } else { + point = const_cast (&tc->tempo()); + } + initial_bpm = point->note_types_per_minute(); +} + +void +TempoCurveDrag::motion (GdkEvent* event, bool first_move) +{ + if (first_move) { + /* get current state */ + _before_state = &map->get_state(); + _editor->begin_reversible_command (_("change tempo")); + } + + double new_bpm = std::max (1.5, initial_bpm - ((current_pointer_x() - grab_x()) / 5.0)); + stringstream strs; + Temporal::Tempo new_tempo (new_bpm, point->note_type()); + map->change_tempo (*point, new_tempo); + strs << "Tempo: " << fixed << setprecision(3) << new_bpm; + show_verbose_cursor_text (strs.str()); + + _editor->mid_tempo_change (); +} + + +void +TempoCurveDrag::finished (GdkEvent* event, bool movement_occurred) +{ + if (!movement_occurred) { + /* reset the per-thread tempo map ptr back to the current + * official version + */ + + _editor->abort_tempo_map_edit (); + + if (was_double_click()) { + // XXX would be nice to do this + // _editor->edit_tempo_marker (*_marker); + } + + return; + } + + /* push the current state of our writable map copy */ + + TempoMap::update (map); + XMLNode &after = map->get_state(); + + _editor->session()->add_command (new Temporal::TempoCommand (_("change tempo"), _before_state, &after)); + _editor->commit_reversible_command (); +} + +void +TempoCurveDrag::aborted (bool moved) +{ + /* reset the per-thread tempo map ptr back to the current + * official version + */ + + _editor->abort_tempo_map_edit (); +} + TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i) : Drag (e, i, Temporal::BeatTime) , _grab_bpm (120.0, 4.0) diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 4c38608076..370cb097dc 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -76,6 +76,7 @@ class MidiRegionView; class MeterMarker; class ArdourMarker; class TempoMarker; +class TempoCurve; class ControlPoint; class AudioRegionView; class AutomationLine; @@ -860,6 +861,24 @@ private: XMLNode* before_state; }; +/** Tempo curve drag */ +class TempoCurveDrag : public Drag +{ +public: + TempoCurveDrag (Editor*, ArdourCanvas::Item*); + + void start_grab (GdkEvent *, Gdk::Cursor* c = 0); + void motion (GdkEvent *, bool); + void finished (GdkEvent *, bool); + void aborted (bool); + +private: + Temporal::TempoPoint* point; + double initial_bpm; + Temporal::TempoMap::WritableSharedPtr map; + XMLNode* _before_state; +}; + /** Tempo marker drag */ class TempoMarkerDrag : public Drag { diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index a5c685fff9..3adfd7e65d 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -816,9 +816,14 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT return true; break; - case MarkerBarItem: case TempoBarItem: case TempoCurveItem: + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { + _drags->set (new TempoCurveDrag (this, item), event); + return true; + } + /* fallthru */ + case MarkerBarItem: case MeterBarItem: case TimecodeRulerItem: case SamplesRulerItem: diff --git a/gtk2_ardour/tempo_curve.cc b/gtk2_ardour/tempo_curve.cc index 55dd803356..fdc19fd68d 100644 --- a/gtk2_ardour/tempo_curve.cc +++ b/gtk2_ardour/tempo_curve.cc @@ -99,13 +99,14 @@ TempoCurve::TempoCurve (PublicEditor& ed, ArdourCanvas::Item& parent, guint32 rg * make sure they can both be used to lookup this object. */ - _curve->set_data ("tempo curve", this); + _curve->set_data (X_("tempo curve"), this); if (handle_events) { - //group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_marker_event), group, this)); + // group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_marker_event), group, this)); } group->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_tempo_curve_event), _curve, this)); + _curve->Event.connect (sigc::bind (sigc::mem_fun (editor, &PublicEditor::canvas_tempo_curve_event), _curve, this)); }