/* use the new marker for the grab */
swap_grab (&_marker->the_item(), 0, GDK_CURRENT_TIME);
+ _marker->hide();
+ TempoMap& map (_editor->session()->tempo_map());
+ /* get current state */
+ before_state = &map.get_state();
if (!_copy) {
_editor->begin_reversible_command (_("move tempo mark"));
- TempoMap& map (_editor->session()->tempo_map());
- /* get current state */
- before_state = &map.get_state();
+ } else {
+ _editor->begin_reversible_command (_("copy tempo mark"));
+ framepos_t frame;
+ bool use_snap = false;
+
+ if (!_editor->snap_musical()) {
+ frame = adjusted_current_frame (event);
+ } else {
+ frame = adjusted_current_frame (event, false);
+ if (ArdourKeyboard::indicates_snap (event->button.state)) {
+ if (_editor->snap_mode() == Editing::SnapOff) {
+ use_snap = true;
+ } else {
+ use_snap = false;
+ }
+ } else {
+ if (_editor->snap_mode() == Editing::SnapOff) {
+ use_snap = false;
+ } else {
+ use_snap = true;
+ }
+ }
+ }
+
+ Timecode::BBT_Time bbt;
+ map.bbt_time (frame, bbt);
+
+ /* add new tempo section to map, ensuring we don't refer to existing tempos for snap */
+
+ if (_real_section->position_lock_style() == MusicTime) {
+ if (use_snap && _editor->snap_type() == SnapToBar) {
+ map.round_bbt (bbt, -1);
+ } else if (use_snap) {
+ map.round_bbt (bbt, _editor->get_grid_beat_divisions (0));
+ }
+ double const pulse = map.predict_tempo_pulse (_real_section, map.frame_time (bbt));
+ _real_section = map.add_tempo (_marker->tempo(), pulse, _real_section->type());
+ } else {
+ if (use_snap && _editor->snap_type() == SnapToBar) {
+ map.round_bbt (bbt, -1);
+ } else if (use_snap) {
+ map.round_bbt (bbt, _editor->get_grid_beat_divisions (0));
+ }
+ if (use_snap) {
+ frame = map.predict_tempo_frame (_real_section, bbt);
+ }
+ _real_section = map.add_tempo (_marker->tempo(), frame, _real_section->type());
+ }
}
- _marker->hide();
+
}
framepos_t pf;
Tempo const tp = _marker->tempo();
- if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::constraint_modifier ())) {
+ if (ArdourKeyboard::indicates_snap (event->button.state)) {
double new_bpm = _real_section->beats_per_minute() + ((last_pointer_y() - current_pointer_y()) / 5.0);
_editor->session()->tempo_map().gui_change_tempo (_real_section, Tempo (new_bpm, _real_section->note_type()));
stringstream strs;
show_verbose_cursor_text (strs.str());
} else if (_movable) {
if (!_editor->snap_musical()) {
+ /* snap normally (this is not self-referential).*/
pf = adjusted_current_frame (event);
} else {
+ /* but this is.
+ we can't use the map for anything related to tempo,
+ so we round bbt using meters, which have no dependency
+ on pulse for this kind of thing.
+ */
bool use_snap;
TempoMap& map (_editor->session()->tempo_map());
return;
}
-
TempoMap& map (_editor->session()->tempo_map());
- if (_copy == true) {
- _editor->begin_reversible_command (_("copy tempo mark"));
- XMLNode &before = map.get_state();
-
- if (_marker->tempo().position_lock_style() == MusicTime) {
- double const pulse = map.predict_tempo_pulse (_real_section, _real_section->frame());
- map.add_tempo (_marker->tempo(), pulse, _marker->tempo().type());
- } else {
- map.add_tempo (_marker->tempo(), _real_section->frame(), _marker->tempo().type());
- }
-
- XMLNode &after = map.get_state();
- _editor->session()->add_command (new MementoCommand<TempoMap>(map, &before, &after));
- _editor->commit_reversible_command ();
-
- } else {
- if (_marker->tempo().position_lock_style() == MusicTime) {
- double const pulse = map.predict_tempo_pulse (_real_section, _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 (_real_section->beats_per_minute(), _real_section->note_type())
- , _real_section->frame(), _marker->tempo().type());
- }
-
- XMLNode &after = map.get_state();
- _editor->session()->add_command (new MementoCommand<TempoMap>(map, before_state, &after));
- _editor->commit_reversible_command ();
- }
+ XMLNode &after = map.get_state();
+ _editor->session()->add_command (new MementoCommand<TempoMap>(map, before_state, &after));
+ _editor->commit_reversible_command ();
// delete the dummy marker we used for visual representation while moving.
// a new visual marker will show up automatically.
_marker->set_position (_marker->tempo().frame());
if (moved) {
TempoMap& map (_editor->session()->tempo_map());
- /* we removed it before, so add it back now */
- if (_marker->tempo().position_lock_style() == MusicTime) {
- map.add_tempo (_marker->tempo(), _marker->tempo().pulse(), _marker->tempo().type());
- } else {
- map.add_tempo (_marker->tempo(), _marker->tempo().frame(), _marker->tempo().type());
- }
+ map.set_state (*before_state, Stateful::current_state_version);
// delete the dummy marker we used for visual representation while moving.
// a new visual marker will show up automatically.
delete _marker;
const MeterSection& meter_section_at (framepos_t frame) const;
const MeterSection& meter_section_at (const double& beat) const;
- void add_tempo (const Tempo&, const double& pulse, TempoSection::Type type);
- void add_tempo (const Tempo&, const framepos_t& frame, TempoSection::Type type);
+ TempoSection* add_tempo (const Tempo&, const double& pulse, TempoSection::Type type);
+ TempoSection* add_tempo (const Tempo&, const framepos_t& frame, TempoSection::Type type);
MeterSection* add_meter (const Meter&, const double& beat, const Timecode::BBT_Time& where);
MeterSection* add_meter (const Meter&, const framepos_t& frame, const double& beat, const Timecode::BBT_Time& where);
void do_insert (MetricSection* section);
- void add_tempo_locked (const Tempo&, double pulse, bool recompute, TempoSection::Type type);
- void add_tempo_locked (const Tempo&, framepos_t frame, bool recompute, TempoSection::Type type);
+ TempoSection* add_tempo_locked (const Tempo&, double pulse, bool recompute, TempoSection::Type type);
+ TempoSection* add_tempo_locked (const Tempo&, framepos_t frame, bool recompute, TempoSection::Type type);
MeterSection* add_meter_locked (const Meter&, double beat, Timecode::BBT_Time where, bool recompute);
MeterSection* add_meter_locked (const Meter&, framepos_t frame, double beat, Timecode::BBT_Time where, bool recompute);
TempoSection::tempo_at_frame (const framepos_t& f, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return pulses_per_minute();
}
framepos_t
TempoSection::frame_at_tempo (const double& ppm, const double& b, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return ((b - pulse()) * frames_per_pulse (frame_rate)) + frame();
}
TempoSection::tempo_at_pulse (const double& p) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return pulses_per_minute();
}
double const ppm = pulse_tempo_at_pulse (p - pulse());
double
TempoSection::pulse_at_tempo (const double& ppm, const framepos_t& f, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
double const pulses = ((f - frame()) / frames_per_pulse (frame_rate)) + pulse();
return pulses;
}
double
TempoSection::pulse_at_frame (const framepos_t& f, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return ((f - frame()) / frames_per_pulse (frame_rate)) + pulse();
}
framepos_t
TempoSection::frame_at_pulse (const double& p, const framecnt_t& frame_rate) const
{
- if (_type == Constant) {
+ if (_type == Constant || _c_func == 0.0) {
return (framepos_t) floor ((p - pulse()) * frames_per_pulse (frame_rate)) + frame();
}
PropertyChanged (PropertyChange ());
}
-void
+TempoSection*
TempoMap::add_tempo (const Tempo& tempo, const double& pulse, ARDOUR::TempoSection::Type type)
{
+ TempoSection* ts = 0;
{
Glib::Threads::RWLock::WriterLock lm (lock);
- add_tempo_locked (tempo, pulse, true, type);
+ ts = add_tempo_locked (tempo, pulse, true, type);
}
PropertyChanged (PropertyChange ());
+
+ return ts;
}
-void
+TempoSection*
TempoMap::add_tempo (const Tempo& tempo, const framepos_t& frame, ARDOUR::TempoSection::Type type)
{
+ TempoSection* ts = 0;
{
Glib::Threads::RWLock::WriterLock lm (lock);
- add_tempo_locked (tempo, frame, true, type);
+ ts = add_tempo_locked (tempo, frame, true, type);
}
PropertyChanged (PropertyChange ());
+
+ return ts;
}
-void
+TempoSection*
TempoMap::add_tempo_locked (const Tempo& tempo, double pulse, bool recompute, ARDOUR::TempoSection::Type type)
{
- TempoSection* ts = new TempoSection (pulse, tempo.beats_per_minute(), tempo.note_type(), type);
+ TempoSection* t = new TempoSection (pulse, tempo.beats_per_minute(), tempo.note_type(), type);
- do_insert (ts);
+ do_insert (t);
if (recompute) {
- solve_map (_metrics, ts, ts->pulse());
+ solve_map (_metrics, t, t->pulse());
}
+
+ return t;
}
-void
+TempoSection*
TempoMap::add_tempo_locked (const Tempo& tempo, framepos_t frame, bool recompute, ARDOUR::TempoSection::Type type)
{
- TempoSection* ts = new TempoSection (frame, tempo.beats_per_minute(), tempo.note_type(), type);
+ TempoSection* t = new TempoSection (frame, tempo.beats_per_minute(), tempo.note_type(), type);
- do_insert (ts);
+ do_insert (t);
if (recompute) {
- solve_map (_metrics, ts, ts->frame());
+ solve_map (_metrics, t, t->frame());
}
+
+ return t;
}
void
MeterSection*
TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, double beat, Timecode::BBT_Time where, bool recompute)
{
-
MeterSection* new_meter = new MeterSection (frame, beat, where, meter.divisions_per_bar(), meter.note_divisor());
double pulse = pulse_at_frame_locked (_metrics, frame);
if (!t->active()) {
continue;
}
+ if (!t->movable()) {
+ t->set_pulse (0.0);
+ prev_t = t;
+ continue;
+ }
if (prev_t) {
if (t->position_lock_style() == AudioTime) {
prev_t->set_c_func (prev_t->compute_c_func_frame (t->pulses_per_minute(), t->frame(), _frame_rate));
return false;
}
- /* precision check ensures pulses and frames align independent of lock style.*/
- if (by_frame && t->frame() != prev_t->frame_at_pulse (t->pulse(), _frame_rate)) {
+ /* precision check ensures pulses and frames align.*/
+ if (t->frame() != prev_t->frame_at_pulse (t->pulse(), _frame_rate)) {
return false;
}
}
}
if (section->movable() && frame <= first_m_frame) {
return false;
- } else {
- section->set_active (true);
}
+
+ section->set_active (true);
section->set_frame (frame);
for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
} else {
recompute_tempos (imaginary);
}
+
if (check_solved (imaginary, true)) {
recompute_meters (imaginary);
return true;
}
-
+#if (0)
MetricSectionSorter cmp;
imaginary.sort (cmp);
if (section->position_lock_style() == MusicTime) {
} else {
recompute_tempos (imaginary);
}
+
if (check_solved (imaginary, true)) {
recompute_meters (imaginary);
return true;
}
+#endif
//dump (imaginary, std::cerr);
return false;
if (!t->active()) {
continue;
}
+ if (!t->movable()) {
+ t->set_pulse (0.0);
+ prev_t = t;
+ continue;
+ }
if (prev_t) {
if (t == section) {
section_prev = prev_t;
} else {
recompute_tempos (imaginary);
}
+
if (check_solved (imaginary, false)) {
recompute_meters (imaginary);
return true;
}
/** places a copy of _metrics into copy and returns a pointer
- * to section's equivalent.
+ * to section's equivalent in copy.
*/
TempoSection*
TempoMap::copy_metrics_and_point (Metrics& copy, TempoSection* section)
{
TempoSection* t;
- TempoSection* ret = 0;
MeterSection* m;
+ TempoSection* ret = 0;
for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
if (t == section) {
if (t->position_lock_style() == MusicTime) {
ret = new TempoSection (t->pulse(), t->beats_per_minute(), t->note_type(), t->type());
+ ret->set_frame (t->frame());
} else {
ret = new TempoSection (t->frame(), t->beats_per_minute(), t->note_type(), t->type());
+ ret->set_pulse (t->pulse());
}
ret->set_active (t->active());
ret->set_movable (t->movable());
TempoSection* cp = 0;
if (t->position_lock_style() == MusicTime) {
cp = new TempoSection (t->pulse(), t->beats_per_minute(), t->note_type(), t->type());
+ cp->set_frame (t->frame());
} else {
cp = new TempoSection (t->frame(), t->beats_per_minute(), t->note_type(), t->type());
+ cp->set_pulse (t->pulse());
}
cp->set_active (t->active());
cp->set_movable (t->movable());
copy.push_back (cp);
}
}
- //recompute_map (copy);
+
return ret;
}
TempoSection* new_section = copy_metrics_and_point (future_map, section);
const double beat = bbt_to_beats_locked (future_map, bbt);
+
if (solve_map (future_map, new_section, pulse_at_beat_locked (future_map, beat))) {
ret = new_section->frame();
} else {
const double tick_at_time = beat_at_frame_locked (_metrics, pos) * BBT_Time::ticks_per_beat;
const double bbt_ticks = bbt.ticks + (bbt.beats * BBT_Time::ticks_per_beat);
const double total_beats = (tick_at_time + bbt_ticks) / BBT_Time::ticks_per_beat;
- const framecnt_t time_at_bbt = frame_at_beat_locked (_metrics, total_beats);
- const framecnt_t ret = time_at_bbt;
- return ret;
+ return frame_at_beat_locked (_metrics, total_beats);
}
framepos_t
}
if ((prev_t) && t->frame() > frame) {
/* t is the section past frame */
- const double ret = prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type();
- const Tempo ret_tempo (ret, prev_t->note_type());
+ const double ret_bpm = prev_t->tempo_at_frame (frame, _frame_rate) * prev_t->note_type();
+ const Tempo ret_tempo (ret_bpm, prev_t->note_type());
return ret_tempo;
}
prev_t = t;
const MeterSection&
TempoMap::meter_section_at_locked (framepos_t frame) const
{
- //framepos_t const frame_off = frame + frame_offset_at (_metrics, frame);
Metrics::const_iterator i;
MeterSection* prev = 0;