summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authornick_m <mainsbridge@gmail.com>2017-03-05 05:21:56 +1100
committernick_m <mainsbridge@gmail.com>2017-03-05 05:21:56 +1100
commit5c741b7a07d12780ba135bcd8509e7ab420cd7da (patch)
treec42f8a6f6de9133e3906bd83975492ac4674bc2e /gtk2_ardour
parent044cfab946649c8006ed1f9f8e770e942a29b51d (diff)
tempo editing updates
- a tempo marker may now be set to always continue (clamped) this means that the end tempo of the previous section will track the start tempo during tempo ops. it mimics the behaviour in 5.8, with the gui indicating the curves to be changed.
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/editor.h1
-rw-r--r--gtk2_ardour/editor_drag.cc126
-rw-r--r--gtk2_ardour/editor_drag.h8
-rw-r--r--gtk2_ardour/editor_markers.cc46
-rw-r--r--gtk2_ardour/editor_tempodisplay.cc4
5 files changed, 131 insertions, 54 deletions
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index ec781e2df6..917dacb53e 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -1688,6 +1688,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void marker_menu_rename ();
void rename_marker (ArdourMarker *marker);
void toggle_marker_lock_style ();
+ void toggle_tempo_clamped ();
void toggle_tempo_type ();
void continue_previous_tempo ();
void ramp_to_next_tempo ();
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index cd60f721bf..1538457f7e 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -3364,7 +3364,7 @@ TempoMarkerDrag::TempoMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c)
, _copy (c)
, _grab_bpm (120.0, 4.0)
, _grab_qn (0.0)
- , before_state (0)
+ , _before_state (0)
{
DEBUG_TRACE (DEBUG::Drags, "New TempoMarkerDrag\n");
@@ -3423,7 +3423,7 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
_marker->hide();
/* get current state */
- before_state = &map.get_state();
+ _before_state = &map.get_state();
if (!_copy) {
_editor->begin_reversible_command (_("move tempo mark"));
@@ -3451,7 +3451,7 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
if (ArdourKeyboard::indicates_constraint (event->button.state) && ArdourKeyboard::indicates_copy (event->button.state)) {
double new_bpm = max (1.5, _grab_bpm.end_note_types_per_minute() + ((grab_y() - min (-1.0, current_pointer_y())) / 5.0));
stringstream strs;
- _editor->session()->tempo_map().gui_change_tempo (_real_section, Tempo (new_bpm, _real_section->note_type()), true);
+ _editor->session()->tempo_map().gui_change_tempo (_real_section, Tempo (_real_section->note_types_per_minute(), _real_section->note_type(), new_bpm));
strs << "end:" << fixed << setprecision(3) << new_bpm;
show_verbose_cursor_text (strs.str());
@@ -3459,7 +3459,7 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move)
/* use vertical movement to alter tempo .. should be log */
double new_bpm = max (1.5, _grab_bpm.note_types_per_minute() + ((grab_y() - min (-1.0, current_pointer_y())) / 5.0));
stringstream strs;
- _editor->session()->tempo_map().gui_change_tempo (_real_section, Tempo (new_bpm, _real_section->note_type()), false);
+ _editor->session()->tempo_map().gui_change_tempo (_real_section, Tempo (new_bpm, _real_section->note_type(), _real_section->end_note_types_per_minute()));
strs << "start:" << fixed << setprecision(3) << new_bpm;
show_verbose_cursor_text (strs.str());
@@ -3501,7 +3501,7 @@ TempoMarkerDrag::finished (GdkEvent* event, bool movement_occurred)
TempoMap& map (_editor->session()->tempo_map());
XMLNode &after = map.get_state();
- _editor->session()->add_command (new MementoCommand<TempoMap>(map, before_state, &after));
+ _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.
@@ -3515,7 +3515,7 @@ TempoMarkerDrag::aborted (bool moved)
_marker->set_position (_marker->tempo().frame());
if (moved) {
TempoMap& map (_editor->session()->tempo_map());
- map.set_state (*before_state, Stateful::current_state_version);
+ map.set_state (*_before_state, Stateful::current_state_version);
// delete the dummy (hidden) marker we used for events while moving.
delete _marker;
}
@@ -3525,7 +3525,7 @@ BBTRulerDrag::BBTRulerDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i)
, _grab_qn (0.0)
, _tempo (0)
- , before_state (0)
+ , _before_state (0)
{
DEBUG_TRACE (DEBUG::Drags, "New BBTRulerDrag\n");
@@ -3540,6 +3540,14 @@ BBTRulerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
_editor->tempo_curve_selected (_tempo, true);
ostringstream sstr;
+ if (_tempo->clamped()) {
+ TempoSection* prev = map.previous_tempo_section (_tempo);
+ if (prev) {
+ _editor->tempo_curve_selected (prev, true);
+ sstr << "end: " << fixed << setprecision(3) << prev->end_note_types_per_minute() << "\n";
+ }
+ }
+
sstr << "start: " << fixed << setprecision(3) << _tempo->note_types_per_minute();
show_verbose_cursor_text (sstr.str());
}
@@ -3548,6 +3556,9 @@ void
BBTRulerDrag::setup_pointer_frame_offset ()
{
TempoMap& map (_editor->session()->tempo_map());
+ /* get current state */
+ _before_state = &map.get_state();
+
const double beat_at_frame = max (0.0, map.beat_at_frame (raw_grab_frame()));
const uint32_t divisions = _editor->get_grid_beat_divisions (0);
double beat = 0.0;
@@ -3574,8 +3585,6 @@ BBTRulerDrag::motion (GdkEvent* event, bool first_move)
TempoMap& map (_editor->session()->tempo_map());
if (first_move) {
- /* get current state */
- before_state = &map.get_state();
_editor->begin_reversible_command (_("stretch tempo"));
}
@@ -3591,7 +3600,15 @@ BBTRulerDrag::motion (GdkEvent* event, bool first_move)
/* adjust previous tempo to match pointer frame */
_editor->session()->tempo_map().gui_stretch_tempo (_tempo, map.frame_at_quarter_note (_grab_qn), pf);
}
+
ostringstream sstr;
+ if (_tempo->clamped()) {
+ TempoSection* prev = map.previous_tempo_section (_tempo);
+ if (prev) {
+ _editor->tempo_curve_selected (prev, true);
+ sstr << "end: " << fixed << setprecision(3) << prev->end_note_types_per_minute() << "\n";
+ }
+ }
sstr << "start: " << fixed << setprecision(3) << _tempo->note_types_per_minute();
show_verbose_cursor_text (sstr.str());
}
@@ -3606,16 +3623,23 @@ BBTRulerDrag::finished (GdkEvent* event, bool movement_occurred)
TempoMap& map (_editor->session()->tempo_map());
XMLNode &after = map.get_state();
- _editor->session()->add_command(new MementoCommand<TempoMap>(map, before_state, &after));
+ _editor->session()->add_command(new MementoCommand<TempoMap>(map, _before_state, &after));
_editor->commit_reversible_command ();
_editor->tempo_curve_selected (_tempo, false);
+
+ if (_tempo->clamped()) {
+ TempoSection* prev_tempo = map.previous_tempo_section (_tempo);
+ if (prev_tempo) {
+ _editor->tempo_curve_selected (prev_tempo, false);
+ }
+ }
}
void
BBTRulerDrag::aborted (bool moved)
{
if (moved) {
- _editor->session()->tempo_map().set_state (*before_state, Stateful::current_state_version);
+ _editor->session()->tempo_map().set_state (*_before_state, Stateful::current_state_version);
}
}
@@ -3626,7 +3650,7 @@ TempoTwistDrag::TempoTwistDrag (Editor* e, ArdourCanvas::Item* i)
, _tempo (0)
, _next_tempo (0)
, _drag_valid (true)
- , before_state (0)
+ , _before_state (0)
{
DEBUG_TRACE (DEBUG::Drags, "New TempoTwistDrag\n");
@@ -3637,6 +3661,8 @@ TempoTwistDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{
Drag::start_grab (event, cursor);
TempoMap& map (_editor->session()->tempo_map());
+ /* get current state */
+ _before_state = &map.get_state();
_tempo = const_cast<TempoSection*> (&map.tempo_section_at_frame (raw_grab_frame()));
_next_tempo = map.next_tempo_section (_tempo);
@@ -3697,8 +3723,6 @@ TempoTwistDrag::motion (GdkEvent* event, bool first_move)
TempoMap& map (_editor->session()->tempo_map());
if (first_move) {
- /* get current state */
- before_state = &map.get_state();
_editor->begin_reversible_command (_("twist tempo"));
}
@@ -3734,7 +3758,7 @@ TempoTwistDrag::finished (GdkEvent* event, bool movement_occurred)
_editor->tempo_curve_selected (_next_tempo, false);
XMLNode &after = map.get_state();
- _editor->session()->add_command(new MementoCommand<TempoMap>(map, before_state, &after));
+ _editor->session()->add_command(new MementoCommand<TempoMap>(map, _before_state, &after));
_editor->commit_reversible_command ();
}
@@ -3742,7 +3766,7 @@ void
TempoTwistDrag::aborted (bool moved)
{
if (moved) {
- _editor->session()->tempo_map().set_state (*before_state, Stateful::current_state_version);
+ _editor->session()->tempo_map().set_state (*_before_state, Stateful::current_state_version);
}
}
@@ -3750,22 +3774,37 @@ TempoEndDrag::TempoEndDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i)
, _grab_qn (0.0)
, _tempo (0)
- , before_state (0)
+ , _before_state (0)
{
DEBUG_TRACE (DEBUG::Drags, "New TempoEndDrag\n");
-
+ TempoMarker* marker = reinterpret_cast<TempoMarker*> (_item->get_data ("marker"));
+ _tempo = &marker->tempo();
+ _grab_qn = _tempo->pulse() * 4.0;
}
void
TempoEndDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{
Drag::start_grab (event, cursor);
- TempoMap& map (_editor->session()->tempo_map());
- _tempo = const_cast<TempoSection*> (&map.tempo_section_at_frame (raw_grab_frame()));
- _editor->tempo_curve_selected (&map.tempo_section_at_frame (_tempo->frame() - 1), true);
+ TempoMap& tmap (_editor->session()->tempo_map());
+
+ /* get current state */
+ _before_state = &tmap.get_state();
+
ostringstream sstr;
- sstr << "end: " << fixed << setprecision(3) << map.tempo_section_at_frame (_tempo->frame() - 1).end_note_types_per_minute() << "\n";
+
+ TempoSection* prev = 0;
+ if ((prev = tmap.previous_tempo_section (_tempo)) != 0) {
+ _editor->tempo_curve_selected (tmap.previous_tempo_section (_tempo), true);
+ sstr << "end: " << fixed << setprecision(3) << tmap.tempo_section_at_frame (_tempo->frame() - 1).end_note_types_per_minute() << "\n";
+ }
+
+ if (_tempo->clamped()) {
+ _editor->tempo_curve_selected (_tempo, true);
+ sstr << "start: " << fixed << setprecision(3) << _tempo->note_types_per_minute();
+ }
+
show_verbose_cursor_text (sstr.str());
}
@@ -3773,21 +3812,6 @@ void
TempoEndDrag::setup_pointer_frame_offset ()
{
TempoMap& map (_editor->session()->tempo_map());
- const double beat_at_frame = max (0.0, map.beat_at_frame (raw_grab_frame()));
- const uint32_t divisions = _editor->get_grid_beat_divisions (0);
- double beat = 0.0;
-
- if (divisions > 0) {
- beat = floor (beat_at_frame) + (floor (((beat_at_frame - floor (beat_at_frame)) * divisions)) / divisions);
- } else {
- /* while it makes some sense for the user to determine the division to 'grab',
- grabbing a bar often leads to confusing results wrt the actual tempo section being altered
- and the result over steep tempo curves. Use sixteenths.
- */
- beat = floor (beat_at_frame) + (floor (((beat_at_frame - floor (beat_at_frame)) * 4)) / 4);
- }
-
- _grab_qn = map.quarter_note_at_beat (beat);
_pointer_frame_offset = raw_grab_frame() - map.frame_at_quarter_note (_grab_qn);
@@ -3799,8 +3823,6 @@ TempoEndDrag::motion (GdkEvent* event, bool first_move)
TempoMap& map (_editor->session()->tempo_map());
if (first_move) {
- /* get current state */
- before_state = &map.get_state();
_editor->begin_reversible_command (_("stretch end tempo"));
}
@@ -3810,7 +3832,12 @@ TempoEndDrag::motion (GdkEvent* event, bool first_move)
map.gui_stretch_tempo_end (&map.tempo_section_at_frame (_tempo->frame() - 1), map.frame_at_quarter_note (_grab_qn), pf);
ostringstream sstr;
- sstr << "end: " << fixed << setprecision(3) << map.tempo_section_at_frame (_tempo->frame() - 1).end_note_types_per_minute();
+ sstr << "end: " << fixed << setprecision(3) << map.tempo_section_at_frame (_tempo->frame() - 1).end_note_types_per_minute() << "\n";
+
+ if (_tempo->clamped()) {
+ sstr << "start: " << fixed << setprecision(3) << _tempo->note_types_per_minute();
+ }
+
show_verbose_cursor_text (sstr.str());
}
@@ -3821,19 +3848,28 @@ TempoEndDrag::finished (GdkEvent* event, bool movement_occurred)
return;
}
- TempoMap& map (_editor->session()->tempo_map());
+ TempoMap& tmap (_editor->session()->tempo_map());
- XMLNode &after = map.get_state();
- _editor->session()->add_command(new MementoCommand<TempoMap>(map, before_state, &after));
+ XMLNode &after = tmap.get_state();
+ _editor->session()->add_command(new MementoCommand<TempoMap>(tmap, _before_state, &after));
_editor->commit_reversible_command ();
- _editor->tempo_curve_selected (&map.tempo_section_at_frame (_tempo->frame() - 1), false);
+
+ TempoSection* prev = 0;
+ if ((prev = tmap.previous_tempo_section (_tempo)) != 0) {
+ _editor->tempo_curve_selected (prev, false);
+ }
+
+ if (_tempo->clamped()) {
+ _editor->tempo_curve_selected (_tempo, false);
+
+ }
}
void
TempoEndDrag::aborted (bool moved)
{
if (moved) {
- _editor->session()->tempo_map().set_state (*before_state, Stateful::current_state_version);
+ _editor->session()->tempo_map().set_state (*_before_state, Stateful::current_state_version);
}
}
diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h
index d41ca2708f..84356f4636 100644
--- a/gtk2_ardour/editor_drag.h
+++ b/gtk2_ardour/editor_drag.h
@@ -794,7 +794,7 @@ private:
bool _movable;
ARDOUR::Tempo _grab_bpm;
double _grab_qn;
- XMLNode* before_state;
+ XMLNode* _before_state;
};
/** BBT Ruler drag */
@@ -821,7 +821,7 @@ public:
private:
double _grab_qn;
ARDOUR::TempoSection* _tempo;
- XMLNode* before_state;
+ XMLNode* _before_state;
};
/** tempo curve twist drag */
@@ -851,7 +851,7 @@ private:
ARDOUR::TempoSection* _tempo;
ARDOUR::TempoSection* _next_tempo;
bool _drag_valid;
- XMLNode* before_state;
+ XMLNode* _before_state;
};
@@ -879,7 +879,7 @@ public:
private:
double _grab_qn;
ARDOUR::TempoSection* _tempo;
- XMLNode* before_state;
+ XMLNode* _before_state;
};
/** Drag of the playhead cursor */
diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc
index 66911fc34c..40942e1569 100644
--- a/gtk2_ardour/editor_markers.cc
+++ b/gtk2_ardour/editor_markers.cc
@@ -991,8 +991,17 @@ Editor::build_tempo_marker_menu (TempoMarker* loc, bool can_remove)
MenuList& items = tempo_marker_menu->items();
tempo_marker_menu->set_name ("ArdourContextMenu");
- if (loc->tempo().type() == TempoSection::Ramp) {
- items.push_back (MenuElem (_("Set Constant"), sigc::mem_fun(*this, &Editor::toggle_tempo_type)));
+ if (!loc->tempo().initial()) {
+ if (loc->tempo().clamped()) {
+ items.push_back (MenuElem (_("Unlock Continue"), sigc::mem_fun(*this, &Editor::toggle_tempo_clamped)));
+ } else {
+ items.push_back (MenuElem (_("Lock Continue"), sigc::mem_fun(*this, &Editor::toggle_tempo_clamped)));
+ }
+
+ TempoSection* prev_ts = _session->tempo_map().previous_tempo_section (&loc->tempo());
+ if (prev_ts && prev_ts->end_note_types_per_minute() != loc->tempo().note_types_per_minute()) {
+ items.push_back (MenuElem (_("Continue"), sigc::mem_fun(*this, &Editor::continue_previous_tempo)));
+ }
}
TempoSection* next_ts = _session->tempo_map().next_tempo_section (&loc->tempo());
@@ -1000,9 +1009,8 @@ Editor::build_tempo_marker_menu (TempoMarker* loc, bool can_remove)
items.push_back (MenuElem (_("Ramp to Next"), sigc::mem_fun(*this, &Editor::ramp_to_next_tempo)));
}
- TempoSection* prev_ts = _session->tempo_map().previous_tempo_section (&loc->tempo());
- if (prev_ts && prev_ts->end_note_types_per_minute() != loc->tempo().note_types_per_minute()) {
- items.push_back (MenuElem (_("Continue"), sigc::mem_fun(*this, &Editor::continue_previous_tempo)));
+ if (loc->tempo().type() == TempoSection::Ramp) {
+ items.push_back (MenuElem (_("Set Constant"), sigc::mem_fun(*this, &Editor::toggle_tempo_type)));
}
if (loc->tempo().position_lock_style() == AudioTime && can_remove) {
@@ -1464,6 +1472,34 @@ Editor::toggle_tempo_type ()
commit_reversible_command ();
}
}
+/* clamped locks the previous section end tempo to the start tempo */
+void
+Editor::toggle_tempo_clamped ()
+{
+ TempoMarker* tm;
+ MeterMarker* mm;
+ dynamic_cast_marker_object (marker_menu_item->get_data ("marker"), &mm, &tm);
+
+ if (tm) {
+ begin_reversible_command (_("Clamp Tempo"));
+ XMLNode &before = _session->tempo_map().get_state();
+
+ TempoSection* tsp = &tm->tempo();
+ TempoSection* prev = _session->tempo_map().previous_tempo_section (tsp);
+
+ if (prev) {
+ /* set to the end tempo of the previous section */
+ Tempo new_tempo (prev->end_note_types_per_minute(), prev->note_type(), tsp->end_note_types_per_minute());
+ _session->tempo_map().gui_change_tempo (tsp, new_tempo);
+ }
+
+ tsp->set_clamped (!tsp->clamped());
+
+ XMLNode &after = _session->tempo_map().get_state();
+ _session->add_command(new MementoCommand<TempoMap>(_session->tempo_map(), &before, &after));
+ commit_reversible_command ();
+ }
+}
void
Editor::continue_previous_tempo ()
diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc
index 752373db6e..7f34e19398 100644
--- a/gtk2_ardour/editor_tempodisplay.cc
+++ b/gtk2_ardour/editor_tempodisplay.cc
@@ -316,6 +316,10 @@ Editor::redisplay_tempo (bool immediate_redraw)
void
Editor::tempo_curve_selected (TempoSection* ts, bool yn)
{
+ if (ts == 0) {
+ return;
+ }
+
for (Curves::iterator x = tempo_curves.begin(); x != tempo_curves.end(); ++x) {
if (&(*x)->tempo() == ts) {
if (yn) {