From 69b6379b232f7017892b897f4838f273392f4dc2 Mon Sep 17 00:00:00 2001 From: nick_m Date: Sat, 26 Mar 2016 04:48:29 +1100 Subject: Tempo ramps - pressing constraint modifier keys during tempo drag changes tempo with vertical movement, incorporating beat constraint (if present). - makes it easy to find suitable accelerandos for hit points in conjunction with playhead position, beat-locked tempos and initial meter frame. --- gtk2_ardour/editor_drag.cc | 29 ++++++++++++++++++----------- gtk2_ardour/editor_drag.h | 2 +- gtk2_ardour/editor_mouse.cc | 2 +- gtk2_ardour/editor_tempodisplay.cc | 3 +++ libs/ardour/ardour/tempo.h | 2 ++ libs/ardour/tempo.cc | 34 ++++++++++++++++++++++++++++++++-- 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 77c3e3928e..71367d7a62 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -3312,17 +3312,24 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move) _marker->hide(); } - framepos_t const pf = adjusted_current_frame (event, false); + framepos_t const pf = adjusted_current_frame (event); Tempo const tp = _marker->tempo(); _marker->set_position (pf); - /* just here for a check/laugh - if (_real_section->position_lock_style() == MusicTime) { - const double baf = _editor->session()->tempo_map().beat_at_frame (pf); - _editor->session()->tempo_map().gui_move_tempo_beat (_real_section, tp, baf); + + if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::constraint_modifier ())) { + double new_bpm = tp.beats_per_minute() + ((grab_y() - current_pointer_y()) / 4.0); + _real_section->set_beats_per_minute (new_bpm); + _editor->session()->tempo_map().gui_change_tempo (_real_section, Tempo (new_bpm, _real_section->note_type())); } else { - */ - _editor->session()->tempo_map().gui_move_tempo_frame (_real_section, tp, pf); - //} + /* just here for a check/laugh + if (_real_section->position_lock_style() == MusicTime) { + const double baf = _editor->session()->tempo_map().beat_at_frame (pf); + _editor->session()->tempo_map().gui_move_tempo_beat (_real_section, tp, baf); + } else { + */ + _editor->session()->tempo_map().gui_move_tempo_frame (_real_section, tp, pf); + //} + } show_verbose_cursor_time (pf); } @@ -3362,11 +3369,11 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred) } else { if (_marker->tempo().position_lock_style() == MusicTime) { - double const pulse = map.predict_tempo_pulse (_real_section, _marker->tempo(), _real_section->frame()); - map.replace_tempo (*_real_section, Tempo (_marker->tempo().beats_per_minute(), _marker->tempo().note_type()) + double const pulse = map.predict_tempo_pulse (_real_section, Tempo (_real_section->beats_per_minute(), _real_section->note_type()), _real_section->frame()); + map.replace_tempo (*_real_section, Tempo (_real_section->beats_per_minute(), _real_section->note_type()) , pulse, _marker->tempo().type()); } else { - map.replace_tempo (*_real_section, Tempo (_marker->tempo().beats_per_minute(), _marker->tempo().note_type()) + map.replace_tempo (*_real_section, Tempo (_real_section->beats_per_minute(), _real_section->note_type()) , _real_section->frame(), _marker->tempo().type()); } diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 26029299ce..1864514753 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -727,7 +727,7 @@ public: } bool y_movement_matters () const { - return false; + return true; } void setup_pointer_frame_offset (); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index a1a7b793b6..49aaac68bf 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -684,7 +684,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT new TempoMarkerDrag ( this, item, - Keyboard::modifier_state_contains (event->button.state, Keyboard::CopyModifier) + Keyboard::modifier_state_equals (event->button.state, Keyboard::CopyModifier) ), event ); diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 02b7027442..b6db6280e4 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -143,6 +143,9 @@ Editor::marker_position_changed () if ((tempo_marker = dynamic_cast (*x)) != 0) { if ((ts = &tempo_marker->tempo()) != 0) { tempo_marker->set_position (ts->frame ()); + char buf[64]; + snprintf (buf, sizeof (buf), "%.2f", ts->beats_per_minute()); + tempo_marker->set_name (buf); } } if ((meter_marker = dynamic_cast (*x)) != 0) { diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index 780455ff4b..7ee093de64 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -56,6 +56,7 @@ class LIBARDOUR_API Tempo { : _beats_per_minute (bpm), _note_type(type) {} double beats_per_minute () const { return _beats_per_minute; } + void set_beats_per_minute (double bpm) { _beats_per_minute = bpm; } double note_type () const { return _note_type; } double pulses_per_minute () const { return _beats_per_minute / _note_type; } /** audio samples per beat @@ -387,6 +388,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible void gui_move_tempo_beat (TempoSection*, const Tempo& bpm, const double& frame); void gui_move_meter (MeterSection*, const Meter& mt, const framepos_t& frame); void gui_move_meter (MeterSection*, const Meter& mt, const double& beat); + bool gui_change_tempo (TempoSection*, const Tempo& bpm); bool can_solve_bbt (TempoSection* section, const Tempo& bpm, const Timecode::BBT_Time& bbt); diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index f2c44b2500..7ae36f41c5 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -1159,6 +1159,34 @@ TempoMap::gui_move_meter (MeterSection* ms, const Meter& mt, const double& beat MetricPositionChanged (); // Emit Signal } +bool +TempoMap::gui_change_tempo (TempoSection* ts, const Tempo& bpm) +{ + Metrics future_map; + bool can_solve = false; + { + Glib::Threads::RWLock::WriterLock lm (lock); + TempoSection* new_section = copy_metrics_and_point (future_map, ts); + new_section->set_beats_per_minute (bpm.beats_per_minute()); + recompute_tempos (future_map); + + if (check_solved (future_map, true)) { + ts->set_beats_per_minute (bpm.beats_per_minute()); + recompute_map (_metrics); + can_solve = true; + } + } + + Metrics::const_iterator d = future_map.begin(); + while (d != future_map.end()) { + delete (*d); + ++d; + } + if (can_solve) { + MetricPositionChanged (); // Emit Signal + } + return can_solve; +} TempoSection* TempoMap::copy_metrics_and_point (Metrics& copy, TempoSection* section) { @@ -1949,6 +1977,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm MetricSectionSorter cmp; section->set_frame (frame); + for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) { TempoSection* t; if ((t = dynamic_cast (*i)) != 0) { @@ -1970,7 +1999,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm } if (section_prev) { - section_prev->set_c_func (section_prev->compute_c_func_pulse (section->pulses_per_minute(), section->pulse(), _frame_rate)); + section_prev->set_c_func (section_prev->compute_c_func_frame (bpm.pulses_per_minute(), frame, _frame_rate)); section->set_pulse (section_prev->pulse_at_frame (frame, _frame_rate)); } @@ -2029,6 +2058,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm TempoSection* section_prev = 0; section->set_pulse (pulse); + section->set_beats_per_minute (bpm.beats_per_minute()); for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) { TempoSection* t; @@ -2050,7 +2080,7 @@ TempoMap::solve_map (Metrics& imaginary, TempoSection* section, const Tempo& bpm } } if (section_prev) { - section_prev->set_c_func (section_prev->compute_c_func_pulse (section->pulses_per_minute(), pulse, _frame_rate)); + section_prev->set_c_func (section_prev->compute_c_func_pulse (bpm.pulses_per_minute(), pulse, _frame_rate)); section->set_frame (section_prev->frame_at_pulse (pulse, _frame_rate)); } -- cgit v1.2.3