diff options
author | nick_m <mainsbridge@gmail.com> | 2015-12-23 05:58:49 +1100 |
---|---|---|
committer | nick_m <mainsbridge@gmail.com> | 2016-05-27 23:38:09 +1000 |
commit | 340bd42c62a10578eb0314faf67eff115b975c2a (patch) | |
tree | f0d868311715690bdd8b53628877014a30f0dbbe | |
parent | 7898435d3f94355fa0996dc9f85b3bc1ef173585 (diff) |
Tempo ramps - allow live updating of tempo markers.
- all a bit slow, but should be ok once we can lock
markers to frames.
-rw-r--r-- | gtk2_ardour/editor.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.cc | 11 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.h | 3 | ||||
-rw-r--r-- | gtk2_ardour/editor_tempodisplay.cc | 22 | ||||
-rw-r--r-- | libs/ardour/ardour/tempo.h | 8 | ||||
-rw-r--r-- | libs/ardour/tempo.cc | 47 |
7 files changed, 72 insertions, 21 deletions
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 7353b6ff38..0d7717614c 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1365,6 +1365,7 @@ Editor::set_session (Session *t) _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context()); _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context()); _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context()); + _session->tempo_map().MetricPositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::marker_position_changed, this), gui_context()); _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context()); _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context()); _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context()); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 139e044eae..7a2988005d 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1697,6 +1697,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void compute_current_bbt_points (std::vector<ARDOUR::TempoMap::BBTPoint>& grid, framepos_t left, framepos_t right); void tempo_map_changed (const PBD::PropertyChange&); + void marker_position_changed (); void redisplay_tempo (bool immediate_redraw); uint32_t bbt_beat_subdivision; diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 238a0d8ab0..dccb6cac51 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -515,7 +515,6 @@ Drag::add_midi_region (MidiTimeAxisView* view, bool commit) if (_editor->session()) { const TempoMap& map (_editor->session()->tempo_map()); framecnt_t pos = grab_frame(); - const Meter& m = map.meter_at (pos); /* not that the frame rate used here can be affected by pull up/down which might be wrong. */ @@ -3255,6 +3254,7 @@ TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c) DEBUG_TRACE (DEBUG::Drags, "New TempoMarkerDrag\n"); _marker = reinterpret_cast<TempoMarker*> (_item->get_data ("marker")); + _real_section = &_marker->tempo(); assert (_marker); } @@ -3310,12 +3310,15 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move) /* get current state */ before_state = &map.get_state(); /* remove the section while we drag it */ - map.remove_tempo (section, true); + //map.remove_tempo (section, true); } } - framepos_t const pf = adjusted_current_frame (event); + framepos_t const pf = adjusted_current_frame (event, false); + TempoMap& map (_editor->session()->tempo_map()); _marker->set_position (pf); + map.gui_set_tempo_frame (*_real_section, pf); + show_verbose_cursor_time (pf); } @@ -3351,7 +3354,7 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred) } else { /* we removed it before, so add it back now */ - map.add_tempo (_marker->tempo(), when, _marker->tempo().type()); + map.replace_tempo (*_real_section, _marker->tempo().beats_per_minute() , when, _marker->tempo().type()); XMLNode &after = map.get_state(); _editor->session()->add_command (new MementoCommand<TempoMap>(map, before_state, &after)); _editor->commit_reversible_command (); diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index cd1b0c2474..bd2672e23e 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -25,6 +25,7 @@ #include <gdk/gdk.h> #include <stdint.h> +#include "ardour/tempo.h" #include "ardour/types.h" #include "canvas/types.h" @@ -731,6 +732,8 @@ public: private: TempoMarker* _marker; + ARDOUR::TempoSection* _real_section; + bool _copy; XMLNode* before_state; }; diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 2d5a3e47d5..2794051265 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -101,6 +101,7 @@ Editor::draw_metric_marks (const Metrics& metrics) } + void Editor::tempo_map_changed (const PropertyChange& /*ignored*/) { @@ -123,6 +124,27 @@ Editor::tempo_map_changed (const PropertyChange& /*ignored*/) } void +Editor::marker_position_changed () +{ +// yes its identical... + if (!_session) { + return; + } + + ENSURE_GUI_THREAD (*this, &Editor::tempo_map_changed); + + if (tempo_lines) { + tempo_lines->tempo_map_changed(); + } + + std::vector<TempoMap::BBTPoint> grid; + compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples()); + _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); // redraw metric markers + draw_measures (grid); + update_tempo_based_rulers (grid); +} + +void Editor::redisplay_tempo (bool immediate_redraw) { if (!_session) { diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index 5f51124372..403b4c59c9 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -27,6 +27,7 @@ #include <glibmm/threads.h> #include "pbd/undo.h" + #include "pbd/stateful.h" #include "pbd/statefuldestructible.h" @@ -54,7 +55,8 @@ class LIBARDOUR_API Tempo { Tempo (double bpm, double type=4.0) // defaulting to quarter note : _beats_per_minute (bpm), _note_type(type) {} - double beats_per_minute () const { return _beats_per_minute;} + double beats_per_minute () const { return _beats_per_minute; } + double ticks_per_minute () const { return _beats_per_minute * Timecode::BBT_Time::ticks_per_beat;} double note_type () const { return _note_type;} /** audio samples per beat @@ -125,6 +127,7 @@ class LIBARDOUR_API MetricSection { virtual XMLNode& get_state() const = 0; private: + Timecode::BBT_Time _start; framepos_t _frame; bool _movable; @@ -350,6 +353,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible void remove_meter (const MeterSection&, bool send_signal); void replace_tempo (const TempoSection&, const Tempo&, const Timecode::BBT_Time& where, TempoSection::Type type); + void gui_set_tempo_frame (TempoSection&, framepos_t where); void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where); framepos_t round_to_bar (framepos_t frame, RoundMode dir); @@ -383,7 +387,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible int n_meters () const; framecnt_t frame_rate () const { return _frame_rate; } - + PBD::Signal0<void> MetricPositionChanged; private: friend class ::BBTTest; diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index ef7c7d0239..19b25544dc 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -65,6 +65,7 @@ Meter::frames_per_bar (const Tempo& tempo, framecnt_t sr) const return frames_per_grid (tempo, sr) * _divisions_per_bar; } + /***********************************************************************/ const string TempoSection::xml_state_node_name = "Tempo"; @@ -72,7 +73,7 @@ const string TempoSection::xml_state_node_name = "Tempo"; TempoSection::TempoSection (const XMLNode& node) : MetricSection (BBT_Time()), Tempo (TempoMap::default_tempo()) { - XMLProperty const * prop; + const XMLProperty *prop; BBT_Time start; LocaleGuard lg; @@ -326,7 +327,8 @@ TempoSection::update_bbt_time_from_bar_offset (const Meter& meter) double ticks = BBT_Time::ticks_per_beat * meter.divisions_per_bar() * _bar_offset; new_start.beats = (uint32_t) floor (ticks/BBT_Time::ticks_per_beat); - new_start.ticks = 0; /* (uint32_t) fmod (ticks, BBT_Time::ticks_per_beat); */ + //new_start.ticks = 0; /* (uint32_t) fmod (ticks, BBT_Time::ticks_per_beat); */ + new_start.ticks = (uint32_t) fmod (ticks, BBT_Time::ticks_per_beat); /* remember the 1-based counting properties of beats */ new_start.beats += 1; @@ -443,6 +445,7 @@ TempoMap::TempoMap (framecnt_t fr) metrics.push_back (t); metrics.push_back (m); + } TempoMap::~TempoMap () @@ -647,9 +650,9 @@ TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const BBT_T remove_tempo_locked (ts); add_tempo_locked (tempo, where, true, type); } else { + first.set_type (type); { /* cannot move the first tempo section */ - first.set_type (type); *static_cast<Tempo*>(&first) = tempo; recompute_map (false); } @@ -660,6 +663,28 @@ TempoMap::replace_tempo (const TempoSection& ts, const Tempo& tempo, const BBT_T } void +TempoMap::gui_set_tempo_frame (TempoSection& ts, framepos_t frame) +{ + { + TempoSection& first (first_tempo()); + + if (ts.start() != first.start()) { + BBT_Time bbt; + bbt_time (frame, bbt); + { + Glib::Threads::RWLock::WriterLock lm (lock); + ts.set_frame (frame); + ts.set_start (bbt); + + recompute_map (false); + } + } + } + + MetricPositionChanged (); // Emit Signal +} + +void TempoMap::add_tempo (const Tempo& tempo, BBT_Time where, ARDOUR::TempoSection::Type type) { { @@ -933,13 +958,6 @@ TempoMap::recompute_map (bool reassign_tempo_bbt, framepos_t end) */ end = max_framepos; - } else { - /* - if (!_map.empty ()) { - /* never allow the map to be shortened / - end = max (end, _map.back().frame); - } - */ } DEBUG_TRACE (DEBUG::TempoMath, string_compose ("recomputing tempo map, zero to %1\n", end)); @@ -1051,15 +1069,11 @@ TempoMap::_extend_map (TempoSection* tempo, MeterSection* meter, /*tempo section (t) lies in the previous meter */ double ticks_at_ts = ((((t->start().bars - 1 ) * meter->divisions_per_bar()) + (t->start().beats - 1) ) * BBT_Time::ticks_per_beat) + t->start().ticks; - - double ticks_at_prev_ts = ((((prev_ts->start().bars - 1) * meter->divisions_per_bar()) + (prev_ts->start().beats - 1)) * BBT_Time::ticks_per_beat) + prev_ts->start().ticks; - double ticks_relative_to_prev_ts = ticks_at_ts - ticks_at_prev_ts; /* assume (falsely) that the target tempo is constant */ double length_estimate = (ticks_relative_to_prev_ts / BBT_Time::ticks_per_beat) * meter->frames_per_grid (*t, _frame_rate); if (prev_ts->type() == TempoSection::Type::Constant) { - cerr << "constant type " << endl; length_estimate = (ticks_relative_to_prev_ts / BBT_Time::ticks_per_beat) * prev_ts->frames_per_beat (_frame_rate); } cerr<< "initial length extimate = " << length_estimate << " ticks_relative_to_prev_ts " << ticks_relative_to_prev_ts << endl; @@ -1378,6 +1392,8 @@ TempoMap::frame_at_tick (double tick) const Glib::Threads::RWLock::ReaderLock lm (lock); double accumulated_ticks = 0.0; + double accumulated_ticks_to_prev = 0.0; + const TempoSection* prev_ts = &first_tempo(); uint32_t cnt = 0; @@ -1397,12 +1413,13 @@ TempoMap::frame_at_tick (double tick) const if (tick < accumulated_ticks) { /* prev_ts is the one affecting us. */ - double ticks_in_section = tick - tick_at_frame (prev_ts->frame()); + double ticks_in_section = tick - accumulated_ticks_to_prev; framepos_t section_start = prev_ts->frame(); framepos_t last_time = t->frame() - prev_ts->frame(); double last_beats_per_minute = t->beats_per_minute(); return prev_ts->frame_at_tick (ticks_in_section, last_beats_per_minute, last_time, _frame_rate) + section_start; } + accumulated_ticks_to_prev = accumulated_ticks; prev_ts = t; ++cnt; |