_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());
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;
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.
*/
DEBUG_TRACE (DEBUG::Drags, "New TempoMarkerDrag\n");
_marker = reinterpret_cast<TempoMarker*> (_item->get_data ("marker"));
+ _real_section = &_marker->tempo();
assert (_marker);
}
/* 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);
}
} 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 ();
#include <gdk/gdk.h>
#include <stdint.h>
+#include "ardour/tempo.h"
#include "ardour/types.h"
#include "canvas/types.h"
private:
TempoMarker* _marker;
+ ARDOUR::TempoSection* _real_section;
+
bool _copy;
XMLNode* before_state;
};
}
+
void
Editor::tempo_map_changed (const PropertyChange& /*ignored*/)
{
update_tempo_based_rulers (grid);
}
+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)
{
#include <glibmm/threads.h>
#include "pbd/undo.h"
+
#include "pbd/stateful.h"
#include "pbd/statefuldestructible.h"
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
virtual XMLNode& get_state() const = 0;
private:
+
Timecode::BBT_Time _start;
framepos_t _frame;
bool _movable;
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);
int n_meters () const;
framecnt_t frame_rate () const { return _frame_rate; }
-
+ PBD::Signal0<void> MetricPositionChanged;
private:
friend class ::BBTTest;
return frames_per_grid (tempo, sr) * _divisions_per_bar;
}
+
/***********************************************************************/
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;
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;
metrics.push_back (t);
metrics.push_back (m);
+
}
TempoMap::~TempoMap ()
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);
}
PropertyChanged (PropertyChange ());
}
+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)
{
*/
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));
/*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;
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;
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;